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.
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/common/pepper_file_util.h"
11 #include "content/public/renderer/renderer_ppapi_host.h"
12 #include "content/renderer/pepper/gfx_conversion.h"
13 #include "content/renderer/pepper/host_globals.h"
14 #include "content/renderer/pepper/pepper_video_encoder_host.h"
15 #include "content/renderer/pepper/video_encoder_shim.h"
16 #include "content/renderer/render_thread_impl.h"
17 #include "media/base/bind_to_current_loop.h"
18 #include "media/base/video_frame.h"
19 #include "media/renderers/gpu_video_accelerator_factories.h"
20 #include "media/video/video_encode_accelerator.h"
21 #include "ppapi/c/pp_codecs.h"
22 #include "ppapi/c/pp_errors.h"
23 #include "ppapi/c/pp_graphics_3d.h"
24 #include "ppapi/host/dispatch_host_message.h"
25 #include "ppapi/host/ppapi_host.h"
26 #include "ppapi/proxy/ppapi_messages.h"
27 #include "ppapi/shared_impl/media_stream_buffer.h"
29 using ppapi::proxy::SerializedHandle
;
35 const uint32_t kDefaultNumberOfBitstreamBuffers
= 4;
37 int32_t PP_FromMediaEncodeAcceleratorError(
38 media::VideoEncodeAccelerator::Error error
) {
40 case media::VideoEncodeAccelerator::kInvalidArgumentError
:
41 return PP_ERROR_MALFORMED_INPUT
;
42 case media::VideoEncodeAccelerator::kIllegalStateError
:
43 case media::VideoEncodeAccelerator::kPlatformFailureError
:
44 return PP_ERROR_RESOURCE_FAILED
;
45 // No default case, to catch unhandled enum values.
47 return PP_ERROR_FAILED
;
50 // TODO(llandwerlin): move following to media_conversion.cc/h?
51 media::VideoCodecProfile
PP_ToMediaVideoProfile(PP_VideoProfile profile
) {
53 case PP_VIDEOPROFILE_H264BASELINE
:
54 return media::H264PROFILE_BASELINE
;
55 case PP_VIDEOPROFILE_H264MAIN
:
56 return media::H264PROFILE_MAIN
;
57 case PP_VIDEOPROFILE_H264EXTENDED
:
58 return media::H264PROFILE_EXTENDED
;
59 case PP_VIDEOPROFILE_H264HIGH
:
60 return media::H264PROFILE_HIGH
;
61 case PP_VIDEOPROFILE_H264HIGH10PROFILE
:
62 return media::H264PROFILE_HIGH10PROFILE
;
63 case PP_VIDEOPROFILE_H264HIGH422PROFILE
:
64 return media::H264PROFILE_HIGH422PROFILE
;
65 case PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE
:
66 return media::H264PROFILE_HIGH444PREDICTIVEPROFILE
;
67 case PP_VIDEOPROFILE_H264SCALABLEBASELINE
:
68 return media::H264PROFILE_SCALABLEBASELINE
;
69 case PP_VIDEOPROFILE_H264SCALABLEHIGH
:
70 return media::H264PROFILE_SCALABLEHIGH
;
71 case PP_VIDEOPROFILE_H264STEREOHIGH
:
72 return media::H264PROFILE_STEREOHIGH
;
73 case PP_VIDEOPROFILE_H264MULTIVIEWHIGH
:
74 return media::H264PROFILE_MULTIVIEWHIGH
;
75 case PP_VIDEOPROFILE_VP8_ANY
:
76 return media::VP8PROFILE_ANY
;
77 case PP_VIDEOPROFILE_VP9_ANY
:
78 return media::VP9PROFILE_ANY
;
79 // No default case, to catch unhandled PP_VideoProfile values.
81 return media::VIDEO_CODEC_PROFILE_UNKNOWN
;
84 PP_VideoProfile
PP_FromMediaVideoProfile(media::VideoCodecProfile profile
) {
86 case media::H264PROFILE_BASELINE
:
87 return PP_VIDEOPROFILE_H264BASELINE
;
88 case media::H264PROFILE_MAIN
:
89 return PP_VIDEOPROFILE_H264MAIN
;
90 case media::H264PROFILE_EXTENDED
:
91 return PP_VIDEOPROFILE_H264EXTENDED
;
92 case media::H264PROFILE_HIGH
:
93 return PP_VIDEOPROFILE_H264HIGH
;
94 case media::H264PROFILE_HIGH10PROFILE
:
95 return PP_VIDEOPROFILE_H264HIGH10PROFILE
;
96 case media::H264PROFILE_HIGH422PROFILE
:
97 return PP_VIDEOPROFILE_H264HIGH422PROFILE
;
98 case media::H264PROFILE_HIGH444PREDICTIVEPROFILE
:
99 return PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE
;
100 case media::H264PROFILE_SCALABLEBASELINE
:
101 return PP_VIDEOPROFILE_H264SCALABLEBASELINE
;
102 case media::H264PROFILE_SCALABLEHIGH
:
103 return PP_VIDEOPROFILE_H264SCALABLEHIGH
;
104 case media::H264PROFILE_STEREOHIGH
:
105 return PP_VIDEOPROFILE_H264STEREOHIGH
;
106 case media::H264PROFILE_MULTIVIEWHIGH
:
107 return PP_VIDEOPROFILE_H264MULTIVIEWHIGH
;
108 case media::VP8PROFILE_ANY
:
109 return PP_VIDEOPROFILE_VP8_ANY
;
110 case media::VP9PROFILE_ANY
:
111 return PP_VIDEOPROFILE_VP9_ANY
;
114 return static_cast<PP_VideoProfile
>(-1);
118 media::VideoFrame::Format
PP_ToMediaVideoFormat(PP_VideoFrame_Format format
) {
120 case PP_VIDEOFRAME_FORMAT_UNKNOWN
:
121 return media::VideoFrame::UNKNOWN
;
122 case PP_VIDEOFRAME_FORMAT_YV12
:
123 return media::VideoFrame::YV12
;
124 case PP_VIDEOFRAME_FORMAT_I420
:
125 return media::VideoFrame::I420
;
126 case PP_VIDEOFRAME_FORMAT_BGRA
:
127 return media::VideoFrame::UNKNOWN
;
128 // No default case, to catch unhandled PP_VideoFrame_Format values.
130 return media::VideoFrame::UNKNOWN
;
133 PP_VideoFrame_Format
PP_FromMediaVideoFormat(media::VideoFrame::Format format
) {
135 case media::VideoFrame::UNKNOWN
:
136 return PP_VIDEOFRAME_FORMAT_UNKNOWN
;
137 case media::VideoFrame::YV12
:
138 return PP_VIDEOFRAME_FORMAT_YV12
;
139 case media::VideoFrame::I420
:
140 return PP_VIDEOFRAME_FORMAT_I420
;
142 return PP_VIDEOFRAME_FORMAT_UNKNOWN
;
146 PP_VideoProfileDescription
PP_FromVideoEncodeAcceleratorSupportedProfile(
147 media::VideoEncodeAccelerator::SupportedProfile profile
,
148 PP_HardwareAcceleration acceleration
) {
149 PP_VideoProfileDescription pp_profile
;
150 pp_profile
.profile
= PP_FromMediaVideoProfile(profile
.profile
);
151 pp_profile
.max_resolution
= PP_FromGfxSize(profile
.max_resolution
);
152 pp_profile
.max_framerate_numerator
= profile
.max_framerate_numerator
;
153 pp_profile
.max_framerate_denominator
= profile
.max_framerate_denominator
;
154 pp_profile
.acceleration
= acceleration
;
158 bool PP_HardwareAccelerationCompatible(PP_HardwareAcceleration supply
,
159 PP_HardwareAcceleration demand
) {
160 // TODO(llandwerlin): Change API to use bool instead of
161 // PP_HardwareAcceleration
163 case PP_HARDWAREACCELERATION_ONLY
:
164 return (demand
== PP_HARDWAREACCELERATION_ONLY
||
165 demand
== PP_HARDWAREACCELERATION_WITHFALLBACK
);
166 case PP_HARDWAREACCELERATION_WITHFALLBACK
:
168 case PP_HARDWAREACCELERATION_NONE
:
169 return (demand
== PP_HARDWAREACCELERATION_WITHFALLBACK
||
170 demand
== PP_HARDWAREACCELERATION_NONE
);
171 // No default case, to catch unhandled PP_HardwareAcceleration values.
178 PepperVideoEncoderHost::ShmBuffer::ShmBuffer(uint32_t id
,
179 scoped_ptr
<base::SharedMemory
> shm
)
180 : id(id
), shm(shm
.Pass()), in_use(true) {
184 PepperVideoEncoderHost::ShmBuffer::~ShmBuffer() {
187 media::BitstreamBuffer
PepperVideoEncoderHost::ShmBuffer::ToBitstreamBuffer() {
188 return media::BitstreamBuffer(id
, shm
->handle(), shm
->mapped_size());
191 PepperVideoEncoderHost::PepperVideoEncoderHost(RendererPpapiHost
* host
,
192 PP_Instance instance
,
193 PP_Resource resource
)
194 : ResourceHost(host
->GetPpapiHost(), instance
, resource
),
195 renderer_ppapi_host_(host
),
196 buffer_manager_(this),
197 command_buffer_(nullptr),
199 encoder_last_error_(PP_ERROR_FAILED
),
201 media_input_format_(media::VideoFrame::UNKNOWN
),
202 weak_ptr_factory_(this) {
205 PepperVideoEncoderHost::~PepperVideoEncoderHost() {
209 int32_t PepperVideoEncoderHost::OnResourceMessageReceived(
210 const IPC::Message
& msg
,
211 ppapi::host::HostMessageContext
* context
) {
212 PPAPI_BEGIN_MESSAGE_MAP(PepperVideoEncoderHost
, msg
)
213 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
214 PpapiHostMsg_VideoEncoder_GetSupportedProfiles
,
215 OnHostMsgGetSupportedProfiles
)
216 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoEncoder_Initialize
,
218 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
219 PpapiHostMsg_VideoEncoder_GetVideoFrames
,
220 OnHostMsgGetVideoFrames
)
221 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoEncoder_Encode
,
223 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
224 PpapiHostMsg_VideoEncoder_RecycleBitstreamBuffer
,
225 OnHostMsgRecycleBitstreamBuffer
)
226 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
227 PpapiHostMsg_VideoEncoder_RequestEncodingParametersChange
,
228 OnHostMsgRequestEncodingParametersChange
)
229 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoEncoder_Close
,
231 PPAPI_END_MESSAGE_MAP()
232 return PP_ERROR_FAILED
;
235 int32_t PepperVideoEncoderHost::OnHostMsgGetSupportedProfiles(
236 ppapi::host::HostMessageContext
* context
) {
237 std::vector
<PP_VideoProfileDescription
> pp_profiles
;
238 GetSupportedProfiles(&pp_profiles
);
241 context
->MakeReplyMessageContext(),
242 PpapiPluginMsg_VideoEncoder_GetSupportedProfilesReply(pp_profiles
));
244 return PP_OK_COMPLETIONPENDING
;
247 int32_t PepperVideoEncoderHost::OnHostMsgInitialize(
248 ppapi::host::HostMessageContext
* context
,
249 PP_VideoFrame_Format input_format
,
250 const PP_Size
& input_visible_size
,
251 PP_VideoProfile output_profile
,
252 uint32_t initial_bitrate
,
253 PP_HardwareAcceleration acceleration
) {
255 return PP_ERROR_FAILED
;
257 media_input_format_
= PP_ToMediaVideoFormat(input_format
);
258 if (media_input_format_
== media::VideoFrame::UNKNOWN
)
259 return PP_ERROR_BADARGUMENT
;
261 media::VideoCodecProfile media_profile
=
262 PP_ToMediaVideoProfile(output_profile
);
263 if (media_profile
== media::VIDEO_CODEC_PROFILE_UNKNOWN
)
264 return PP_ERROR_BADARGUMENT
;
266 gfx::Size
input_size(input_visible_size
.width
, input_visible_size
.height
);
267 if (input_size
.IsEmpty())
268 return PP_ERROR_BADARGUMENT
;
270 if (!IsInitializationValid(input_visible_size
, output_profile
, acceleration
))
271 return PP_ERROR_NOTSUPPORTED
;
273 int32_t error
= PP_ERROR_NOTSUPPORTED
;
274 initialize_reply_context_
= context
->MakeReplyMessageContext();
276 if (acceleration
!= PP_HARDWAREACCELERATION_NONE
) {
277 if (InitializeHardware(media_input_format_
, input_size
, media_profile
,
279 return PP_OK_COMPLETIONPENDING
;
281 if (acceleration
== PP_HARDWAREACCELERATION_ONLY
)
282 error
= PP_ERROR_FAILED
;
285 #if defined(OS_ANDROID)
286 initialize_reply_context_
= ppapi::host::ReplyMessageContext();
290 if (acceleration
!= PP_HARDWAREACCELERATION_ONLY
) {
291 encoder_
.reset(new VideoEncoderShim(this));
292 if (encoder_
->Initialize(media_input_format_
, input_size
, media_profile
,
293 initial_bitrate
, this))
294 return PP_OK_COMPLETIONPENDING
;
295 error
= PP_ERROR_FAILED
;
298 initialize_reply_context_
= ppapi::host::ReplyMessageContext();
304 int32_t PepperVideoEncoderHost::OnHostMsgGetVideoFrames(
305 ppapi::host::HostMessageContext
* context
) {
306 if (encoder_last_error_
)
307 return encoder_last_error_
;
309 get_video_frames_reply_context_
= context
->MakeReplyMessageContext();
310 AllocateVideoFrames();
312 return PP_OK_COMPLETIONPENDING
;
315 int32_t PepperVideoEncoderHost::OnHostMsgEncode(
316 ppapi::host::HostMessageContext
* context
,
318 bool force_keyframe
) {
319 if (encoder_last_error_
)
320 return encoder_last_error_
;
322 if (frame_id
>= frame_count_
)
323 return PP_ERROR_FAILED
;
326 CreateVideoFrame(frame_id
, context
->MakeReplyMessageContext()),
329 return PP_OK_COMPLETIONPENDING
;
332 int32_t PepperVideoEncoderHost::OnHostMsgRecycleBitstreamBuffer(
333 ppapi::host::HostMessageContext
* context
,
334 uint32_t buffer_id
) {
335 if (encoder_last_error_
)
336 return encoder_last_error_
;
338 if (buffer_id
>= shm_buffers_
.size() || shm_buffers_
[buffer_id
]->in_use
)
339 return PP_ERROR_FAILED
;
341 shm_buffers_
[buffer_id
]->in_use
= true;
342 encoder_
->UseOutputBitstreamBuffer(
343 shm_buffers_
[buffer_id
]->ToBitstreamBuffer());
348 int32_t PepperVideoEncoderHost::OnHostMsgRequestEncodingParametersChange(
349 ppapi::host::HostMessageContext
* context
,
351 uint32_t framerate
) {
352 if (encoder_last_error_
)
353 return encoder_last_error_
;
355 encoder_
->RequestEncodingParametersChange(bitrate
, framerate
);
360 int32_t PepperVideoEncoderHost::OnHostMsgClose(
361 ppapi::host::HostMessageContext
* context
) {
362 encoder_last_error_
= PP_ERROR_FAILED
;
368 void PepperVideoEncoderHost::RequireBitstreamBuffers(
369 unsigned int frame_count
,
370 const gfx::Size
& input_coded_size
,
371 size_t output_buffer_size
) {
372 DCHECK(RenderThreadImpl::current());
373 // We assume RequireBitstreamBuffers is only called once.
374 DCHECK(!initialized_
);
376 input_coded_size_
= input_coded_size
;
377 frame_count_
= frame_count
;
379 for (uint32_t i
= 0; i
< kDefaultNumberOfBitstreamBuffers
; ++i
) {
380 scoped_ptr
<base::SharedMemory
> shm(
382 ->HostAllocateSharedMemoryBuffer(output_buffer_size
)
385 if (!shm
|| !shm
->Map(output_buffer_size
)) {
386 shm_buffers_
.clear();
390 shm_buffers_
.push_back(new ShmBuffer(i
, shm
.Pass()));
393 // Feed buffers to the encoder.
394 std::vector
<SerializedHandle
> handles
;
395 for (size_t i
= 0; i
< shm_buffers_
.size(); ++i
) {
396 encoder_
->UseOutputBitstreamBuffer(shm_buffers_
[i
]->ToBitstreamBuffer());
397 handles
.push_back(SerializedHandle(
398 renderer_ppapi_host_
->ShareHandleWithRemote(
399 PlatformFileFromSharedMemoryHandle(shm_buffers_
[i
]->shm
->handle()),
401 output_buffer_size
));
404 host()->SendUnsolicitedReplyWithHandles(
405 pp_resource(), PpapiPluginMsg_VideoEncoder_BitstreamBuffers(
406 static_cast<uint32_t>(output_buffer_size
)),
410 // Tell the plugin that initialization has been successful if we
413 encoder_last_error_
= PP_OK
;
414 host()->SendReply(initialize_reply_context_
,
415 PpapiPluginMsg_VideoEncoder_InitializeReply(
416 frame_count
, PP_FromGfxSize(input_coded_size
)));
419 if (shm_buffers_
.empty()) {
420 NotifyPepperError(PP_ERROR_NOMEMORY
);
424 // If the plugin already requested video frames, we can now answer
426 if (get_video_frames_reply_context_
.is_valid())
427 AllocateVideoFrames();
430 void PepperVideoEncoderHost::BitstreamBufferReady(int32 buffer_id
,
433 DCHECK(RenderThreadImpl::current());
434 DCHECK(shm_buffers_
[buffer_id
]->in_use
);
436 shm_buffers_
[buffer_id
]->in_use
= false;
437 host()->SendUnsolicitedReply(
439 PpapiPluginMsg_VideoEncoder_BitstreamBufferReady(
440 buffer_id
, static_cast<uint32_t>(payload_size
), key_frame
));
443 void PepperVideoEncoderHost::NotifyError(
444 media::VideoEncodeAccelerator::Error error
) {
445 DCHECK(RenderThreadImpl::current());
446 NotifyPepperError(PP_FromMediaEncodeAcceleratorError(error
));
449 void PepperVideoEncoderHost::GetSupportedProfiles(
450 std::vector
<PP_VideoProfileDescription
>* pp_profiles
) {
451 DCHECK(RenderThreadImpl::current());
453 std::vector
<media::VideoEncodeAccelerator::SupportedProfile
> profiles
;
455 if (EnsureGpuChannel()) {
456 profiles
= GpuVideoEncodeAcceleratorHost::ConvertGpuToMediaProfiles(
457 channel_
->gpu_info().video_encode_accelerator_supported_profiles
);
458 for (media::VideoEncodeAccelerator::SupportedProfile profile
: profiles
) {
459 pp_profiles
->push_back(PP_FromVideoEncodeAcceleratorSupportedProfile(
460 profile
, PP_HARDWAREACCELERATION_ONLY
));
464 #if !defined(OS_ANDROID)
465 VideoEncoderShim
software_encoder(this);
466 profiles
= software_encoder
.GetSupportedProfiles();
467 for (media::VideoEncodeAccelerator::SupportedProfile profile
: profiles
) {
468 pp_profiles
->push_back(PP_FromVideoEncodeAcceleratorSupportedProfile(
469 profile
, PP_HARDWAREACCELERATION_NONE
));
474 bool PepperVideoEncoderHost::IsInitializationValid(
475 const PP_Size
& input_size
,
476 PP_VideoProfile output_profile
,
477 PP_HardwareAcceleration acceleration
) {
478 DCHECK(RenderThreadImpl::current());
480 std::vector
<PP_VideoProfileDescription
> profiles
;
481 GetSupportedProfiles(&profiles
);
483 for (const PP_VideoProfileDescription
& profile
: profiles
) {
484 if (output_profile
== profile
.profile
&&
485 input_size
.width
<= profile
.max_resolution
.width
&&
486 input_size
.height
<= profile
.max_resolution
.height
&&
487 PP_HardwareAccelerationCompatible(profile
.acceleration
, acceleration
))
494 bool PepperVideoEncoderHost::EnsureGpuChannel() {
495 DCHECK(RenderThreadImpl::current());
500 // There is no guarantee that we have a 3D context to work with. So
501 // we create a dummy command buffer to communicate with the gpu process.
502 channel_
= RenderThreadImpl::current()->EstablishGpuChannelSync(
503 CAUSE_FOR_GPU_LAUNCH_PEPPERVIDEOENCODERACCELERATOR_INITIALIZE
);
507 std::vector
<int32
> attribs(1, PP_GRAPHICS3DATTRIB_NONE
);
508 command_buffer_
= channel_
->CreateOffscreenCommandBuffer(
509 gfx::Size(), nullptr, attribs
, GURL::EmptyGURL(),
510 gfx::PreferIntegratedGpu
);
511 if (!command_buffer_
) {
516 command_buffer_
->SetChannelErrorCallback(media::BindToCurrentLoop(
517 base::Bind(&PepperVideoEncoderHost::NotifyPepperError
,
518 weak_ptr_factory_
.GetWeakPtr(), PP_ERROR_RESOURCE_FAILED
)));
519 if (!command_buffer_
->Initialize()) {
527 bool PepperVideoEncoderHost::InitializeHardware(
528 media::VideoFrame::Format input_format
,
529 const gfx::Size
& input_visible_size
,
530 media::VideoCodecProfile output_profile
,
531 uint32_t initial_bitrate
) {
532 DCHECK(RenderThreadImpl::current());
534 if (!EnsureGpuChannel())
537 encoder_
= command_buffer_
->CreateVideoEncoder();
539 !encoder_
->Initialize(input_format
, input_visible_size
, output_profile
,
540 initial_bitrate
, this))
546 void PepperVideoEncoderHost::Close() {
547 DCHECK(RenderThreadImpl::current());
550 if (command_buffer_
) {
552 channel_
->DestroyCommandBuffer(command_buffer_
);
553 command_buffer_
= nullptr;
557 void PepperVideoEncoderHost::AllocateVideoFrames() {
558 DCHECK(RenderThreadImpl::current());
559 DCHECK(get_video_frames_reply_context_
.is_valid());
561 // Frames have already been allocated.
562 if (buffer_manager_
.number_of_buffers() > 0) {
563 SendGetFramesErrorReply(PP_ERROR_FAILED
);
568 base::CheckedNumeric
<uint32_t> size
=
569 media::VideoFrame::AllocationSize(media_input_format_
, input_coded_size_
);
570 uint32_t frame_size
= size
.ValueOrDie();
571 size
+= sizeof(ppapi::MediaStreamBuffer::Video
);
572 uint32_t buffer_size
= size
.ValueOrDie();
573 // Make each buffer 4 byte aligned.
574 size
+= (4 - buffer_size
% 4);
575 uint32_t buffer_size_aligned
= size
.ValueOrDie();
576 size
*= frame_count_
;
577 uint32_t total_size
= size
.ValueOrDie();
579 scoped_ptr
<base::SharedMemory
> shm(
580 RenderThreadImpl::current()
581 ->HostAllocateSharedMemoryBuffer(total_size
)
584 !buffer_manager_
.SetBuffers(frame_count_
,
588 SendGetFramesErrorReply(PP_ERROR_NOMEMORY
);
592 VLOG(4) << " frame_count=" << frame_count_
<< " frame_size=" << frame_size
593 << " buffer_size=" << buffer_size_aligned
;
595 for (int32_t i
= 0; i
< buffer_manager_
.number_of_buffers(); ++i
) {
596 ppapi::MediaStreamBuffer::Video
* buffer
=
597 &(buffer_manager_
.GetBufferPointer(i
)->video
);
598 buffer
->header
.size
= buffer_manager_
.buffer_size();
599 buffer
->header
.type
= ppapi::MediaStreamBuffer::TYPE_VIDEO
;
600 buffer
->format
= PP_FromMediaVideoFormat(media_input_format_
);
601 buffer
->size
.width
= input_coded_size_
.width();
602 buffer
->size
.height
= input_coded_size_
.height();
603 buffer
->data_size
= frame_size
;
606 DCHECK(get_video_frames_reply_context_
.is_valid());
607 get_video_frames_reply_context_
.params
.AppendHandle(SerializedHandle(
608 renderer_ppapi_host_
->ShareHandleWithRemote(
609 PlatformFileFromSharedMemoryHandle(buffer_manager_
.shm()->handle()),
613 host()->SendReply(get_video_frames_reply_context_
,
614 PpapiPluginMsg_VideoEncoder_GetVideoFramesReply(
615 frame_count_
, buffer_size_aligned
,
616 PP_FromGfxSize(input_coded_size_
)));
617 get_video_frames_reply_context_
= ppapi::host::ReplyMessageContext();
620 void PepperVideoEncoderHost::SendGetFramesErrorReply(int32_t error
) {
621 get_video_frames_reply_context_
.params
.set_result(error
);
623 get_video_frames_reply_context_
,
624 PpapiPluginMsg_VideoEncoder_GetVideoFramesReply(0, 0, PP_MakeSize(0, 0)));
625 get_video_frames_reply_context_
= ppapi::host::ReplyMessageContext();
628 scoped_refptr
<media::VideoFrame
> PepperVideoEncoderHost::CreateVideoFrame(
630 const ppapi::host::ReplyMessageContext
& reply_context
) {
631 DCHECK(RenderThreadImpl::current());
633 ppapi::MediaStreamBuffer
* buffer
= buffer_manager_
.GetBufferPointer(frame_id
);
635 uint32_t shm_offset
= static_cast<uint8
*>(buffer
->video
.data
) -
636 static_cast<uint8
*>(buffer_manager_
.shm()->memory());
638 return media::VideoFrame::WrapExternalPackedMemory(
639 media_input_format_
, input_coded_size_
, gfx::Rect(input_coded_size_
),
640 input_coded_size_
, static_cast<uint8
*>(buffer
->video
.data
),
641 buffer
->video
.data_size
, buffer_manager_
.shm()->handle(), shm_offset
,
643 base::Bind(&PepperVideoEncoderHost::FrameReleased
,
644 weak_ptr_factory_
.GetWeakPtr(), reply_context
, frame_id
));
647 void PepperVideoEncoderHost::FrameReleased(
648 const ppapi::host::ReplyMessageContext
& reply_context
,
650 DCHECK(RenderThreadImpl::current());
652 ppapi::host::ReplyMessageContext context
= reply_context
;
653 context
.params
.set_result(encoder_last_error_
);
654 host()->SendReply(context
, PpapiPluginMsg_VideoEncoder_EncodeReply(frame_id
));
657 void PepperVideoEncoderHost::NotifyPepperError(int32_t error
) {
658 DCHECK(RenderThreadImpl::current());
660 encoder_last_error_
= error
;
662 host()->SendUnsolicitedReply(
664 PpapiPluginMsg_VideoEncoder_NotifyError(encoder_last_error_
));
667 uint8_t* PepperVideoEncoderHost::ShmHandleToAddress(int32 buffer_id
) {
668 DCHECK(RenderThreadImpl::current());
669 DCHECK_GE(buffer_id
, 0);
670 DCHECK_LT(buffer_id
, static_cast<int32
>(shm_buffers_
.size()));
671 return static_cast<uint8_t*>(shm_buffers_
[buffer_id
]->shm
->memory());
674 } // namespace content