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

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: 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 (c) 2014 The Chromium Authors. All rights reserved.
bbudge 2015/02/10 01:31:07 nit: remove the (c) and 2015
llandwerlin-old 2015/02/10 14:28:12 Done.
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 class BufferManagerDelegate : public ppapi::MediaStreamBufferManager::Delegate {
35 public:
36 BufferManagerDelegate() {}
37 ~BufferManagerDelegate() override {}
bbudge 2015/02/10 01:31:07 You could make the host implement the Delegate int
llandwerlin-old 2015/02/10 14:28:12 Done.
38
39 private:
40 DISALLOW_COPY_AND_ASSIGN(BufferManagerDelegate);
41 };
42
43 base::PlatformFile ConvertSharedMemoryHandle(
44 const base::SharedMemory& shared_memory) {
45 #if defined(OS_POSIX)
46 return shared_memory.handle().fd;
47 #elif defined(OS_WIN)
48 return shared_memory.handle();
49 #else
50 #error "Platform not supported."
51 #endif
52 }
53
54 int32_t PP_FromMediaEncodeAcceleratorError(
55 media::VideoEncodeAccelerator::Error error) {
56 switch (error) {
57 case media::VideoEncodeAccelerator::kInvalidArgumentError:
58 return PP_ERROR_MALFORMED_INPUT;
59 case media::VideoEncodeAccelerator::kIllegalStateError:
60 case media::VideoEncodeAccelerator::kPlatformFailureError:
61 return PP_ERROR_RESOURCE_FAILED;
62 // No default case, to catch unhandled enum values.
63 }
64 return PP_ERROR_FAILED;
65 }
66
67 } // namespace
68
69 // TODO(llandwerlin): move following to media_conversion.cc/h?
70 media::VideoCodecProfile PepperToMediaVideoProfile(PP_VideoProfile profile) {
71 switch (profile) {
72 case PP_VIDEOPROFILE_H264BASELINE:
73 return media::H264PROFILE_BASELINE;
74 case PP_VIDEOPROFILE_H264MAIN:
75 return media::H264PROFILE_MAIN;
76 case PP_VIDEOPROFILE_H264EXTENDED:
77 return media::H264PROFILE_EXTENDED;
78 case PP_VIDEOPROFILE_H264HIGH:
79 return media::H264PROFILE_HIGH;
80 case PP_VIDEOPROFILE_H264HIGH10PROFILE:
81 return media::H264PROFILE_HIGH10PROFILE;
82 case PP_VIDEOPROFILE_H264HIGH422PROFILE:
83 return media::H264PROFILE_HIGH422PROFILE;
84 case PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE:
85 return media::H264PROFILE_HIGH444PREDICTIVEPROFILE;
86 case PP_VIDEOPROFILE_H264SCALABLEBASELINE:
87 return media::H264PROFILE_SCALABLEBASELINE;
88 case PP_VIDEOPROFILE_H264SCALABLEHIGH:
89 return media::H264PROFILE_SCALABLEHIGH;
90 case PP_VIDEOPROFILE_H264STEREOHIGH:
91 return media::H264PROFILE_STEREOHIGH;
92 case PP_VIDEOPROFILE_H264MULTIVIEWHIGH:
93 return media::H264PROFILE_MULTIVIEWHIGH;
94 case PP_VIDEOPROFILE_VP8_ANY:
95 return media::VP8PROFILE_ANY;
96 case PP_VIDEOPROFILE_VP9_ANY:
97 return media::VP9PROFILE_ANY;
98 // No default case, to catch unhandled PP_VideoProfile values.
99 }
100
101 return media::VIDEO_CODEC_PROFILE_UNKNOWN;
102 }
103
104 PP_VideoProfile MediaToPepperVideoProfile(media::VideoCodecProfile profile) {
105 switch (profile) {
106 case media::H264PROFILE_BASELINE:
107 return PP_VIDEOPROFILE_H264BASELINE;
108 case media::H264PROFILE_MAIN:
109 return PP_VIDEOPROFILE_H264MAIN;
110 case media::H264PROFILE_EXTENDED:
111 return PP_VIDEOPROFILE_H264EXTENDED;
112 case media::H264PROFILE_HIGH:
113 return PP_VIDEOPROFILE_H264HIGH;
114 case media::H264PROFILE_HIGH10PROFILE:
115 return PP_VIDEOPROFILE_H264HIGH10PROFILE;
116 case media::H264PROFILE_HIGH422PROFILE:
117 return PP_VIDEOPROFILE_H264HIGH422PROFILE;
118 case media::H264PROFILE_HIGH444PREDICTIVEPROFILE:
119 return PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE;
120 case media::H264PROFILE_SCALABLEBASELINE:
121 return PP_VIDEOPROFILE_H264SCALABLEBASELINE;
122 case media::H264PROFILE_SCALABLEHIGH:
123 return PP_VIDEOPROFILE_H264SCALABLEHIGH;
124 case media::H264PROFILE_STEREOHIGH:
125 return PP_VIDEOPROFILE_H264STEREOHIGH;
126 case media::H264PROFILE_MULTIVIEWHIGH:
127 return PP_VIDEOPROFILE_H264MULTIVIEWHIGH;
128 case media::VP8PROFILE_ANY:
129 return PP_VIDEOPROFILE_VP8_ANY;
130 case media::VP9PROFILE_ANY:
131 return PP_VIDEOPROFILE_VP9_ANY;
132 default:
133 // TODO(llandwerlin): This is wrong, but there is no PP_VIDEOPROFILE_NONE.
134 return PP_VIDEOPROFILE_VP9_ANY;
135 }
136 }
137
138 media::VideoFrame::Format PepperToMediaVideoFormat(
139 PP_VideoFrame_Format format) {
140 switch (format) {
141 case PP_VIDEOFRAME_FORMAT_UNKNOWN:
142 return media::VideoFrame::UNKNOWN;
143 case PP_VIDEOFRAME_FORMAT_YV12:
144 return media::VideoFrame::YV12;
145 case PP_VIDEOFRAME_FORMAT_I420:
146 return media::VideoFrame::I420;
147 case PP_VIDEOFRAME_FORMAT_BGRA:
148 return media::VideoFrame::UNKNOWN;
149 // No default case, to catch unhandled PP_VideoFrame_Format values.
150 }
151
152 return media::VideoFrame::UNKNOWN;
153 }
154
155 PP_VideoFrame_Format MediaToPepperVideoFormat(
156 media::VideoFrame::Format format) {
157 switch (format) {
158 case media::VideoFrame::UNKNOWN:
159 return PP_VIDEOFRAME_FORMAT_UNKNOWN;
160 case media::VideoFrame::YV12:
161 return PP_VIDEOFRAME_FORMAT_YV12;
162 case media::VideoFrame::I420:
163 return PP_VIDEOFRAME_FORMAT_I420;
164 default:
165 return PP_VIDEOFRAME_FORMAT_UNKNOWN;
166 }
167 }
168
169 ////////////////////////////////////////////////////////////////////////////////
170 //
171 // PepperVideoEncoderHost
172 //
173 ////////////////////////////////////////////////////////////////////////////////
174
175 PepperVideoEncoderHost::ShmBuffer::ShmBuffer(
176 int32_t id,
177 scoped_ptr<base::SharedMemory> memory,
178 size_t size)
179 : id(id), shm(memory.Pass()), in_use(true) {
180 if (shm)
181 shm->Map(size);
182 }
183
184 PepperVideoEncoderHost::ShmBuffer::~ShmBuffer() {
185 }
186
187 media::BitstreamBuffer PepperVideoEncoderHost::ShmBuffer::toBitstreamBuffer() {
188 return media::BitstreamBuffer(id, shm->handle(), shm->mapped_size());
189 }
190
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_delegate_(new BufferManagerDelegate()),
197 buffer_manager_(
198 new ppapi::MediaStreamBufferManager(buffer_manager_delegate_.get())),
199 initialized_(false),
200 encoder_last_error_(PP_ERROR_FAILED),
201 command_buffer_(nullptr),
202 weak_ptr_factory_(this) {
203 }
204
205 PepperVideoEncoderHost::~PepperVideoEncoderHost() {
206 if (command_buffer_) {
207 DCHECK(channel_.get());
208 channel_->DestroyCommandBuffer(command_buffer_);
209 command_buffer_ = NULL;
210 }
211
212 channel_ = NULL;
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(PpapiHostMsg_VideoEncoder_GetVideoFrames,
225 OnHostMsgGetVideoFrames)
226 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoEncoder_Encode,
227 OnHostMsgEncode)
228 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
229 PpapiHostMsg_VideoEncoder_RecycleBitstreamBuffer,
230 OnHostMsgRecycleBitstreamBuffer)
231 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
232 PpapiHostMsg_VideoEncoder_RequestEncodingParametersChange,
233 OnHostMsgRequestEncodingParametersChange)
234 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoEncoder_Close,
235 OnHostMsgClose)
236 PPAPI_END_MESSAGE_MAP()
237 return PP_ERROR_FAILED;
238 }
239
240 int32_t PepperVideoEncoderHost::OnHostMsgGetSupportedProfiles(
241 ppapi::host::HostMessageContext* context) {
242 std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles =
243 RenderThreadImpl::current()
244 ->GetGpuFactories()
245 ->GetVideoEncodeAcceleratorSupportedProfiles();
246 // TODO(llandwerlin): merge software supported profiles.
247
248 std::vector<PP_VideoProfileDescription> pp_profiles;
249 for (media::VideoEncodeAccelerator::SupportedProfile profile : profiles) {
250 PP_VideoProfileDescription pp_profile;
251 pp_profile.profile = MediaToPepperVideoProfile(profile.profile);
252 pp_profile.max_resolution = PP_FromGfxSize(profile.max_resolution);
253 pp_profile.max_framerate_numerator = profile.max_framerate_numerator;
254 pp_profile.max_framerate_denominator = profile.max_framerate_denominator;
255 pp_profile.acceleration = PP_HARDWAREACCELERATION_ONLY;
256 pp_profiles.push_back(pp_profile);
257 }
258
259 host()->SendReply(
260 context->MakeReplyMessageContext(),
261 PpapiPluginMsg_VideoEncoder_GetSupportedProfilesReply(pp_profiles));
262
263 return PP_OK_COMPLETIONPENDING;
264 }
265
266 int32_t PepperVideoEncoderHost::OnHostMsgInitialize(
267 ppapi::host::HostMessageContext* context,
268 PP_VideoFrame_Format input_format,
269 const PP_Size& input_visible_size,
270 PP_VideoProfile output_profile,
271 uint32_t initial_bitrate,
272 PP_HardwareAcceleration acceleration) {
273 scoped_ptr<media::VideoEncodeAccelerator> encoder;
274 if (initialized_)
275 return PP_ERROR_FAILED;
276
277 media_format_ = PepperToMediaVideoFormat(input_format);
278 if (media_format_ == media::VideoFrame::UNKNOWN)
279 return PP_ERROR_NOTSUPPORTED;
280
281 media::VideoCodecProfile media_profile =
282 PepperToMediaVideoProfile(output_profile);
283 gfx::Size input_size(input_visible_size.width, input_visible_size.height);
284
285 initialize_reply_context_ = context->MakeReplyMessageContext();
286
287 // There is no garantee that we have a 3D context to work with. So
288 // we create a dump command buffer to communicate with the gpu
289 // process.
290 channel_ = RenderThreadImpl::current()->EstablishGpuChannelSync(
291 CAUSE_FOR_GPU_LAUNCH_PEPPERVIDEOENCODERACCELERATOR_INITIALIZE);
292 if (!channel_.get())
293 return PP_ERROR_FAILED;
294
295 std::vector<int32> attribs;
296 attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
297
298 command_buffer_ = channel_->CreateOffscreenCommandBuffer(
299 gfx::Size(), nullptr, attribs, GURL::EmptyGURL(),
300 gfx::PreferIntegratedGpu);
301 if (!command_buffer_)
302 return PP_ERROR_FAILED;
303
304 command_buffer_->SetChannelErrorCallback(media::BindToCurrentLoop(base::Bind(
305 &PepperVideoEncoderHost::NotifyPepperError,
306 weak_ptr_factory_.GetWeakPtr(),
307 PP_ERROR_FAILED)));
308
309 if (!command_buffer_->Initialize())
310 return PP_ERROR_FAILED;
311
312 encoder_ = command_buffer_->CreateVideoEncoder();
313
314 if (encoder_.get() &&
315 encoder_->Initialize(media_format_, input_size, media_profile,
316 initial_bitrate, this)) {
317 return PP_OK_COMPLETIONPENDING;
318 }
319
320 // TODO(llandwerlin): Software encoder.
321 return PP_ERROR_NOTSUPPORTED;
322 }
323
324 int32_t PepperVideoEncoderHost::OnHostMsgGetVideoFrames(
325 ppapi::host::HostMessageContext* context) {
326 if (encoder_last_error_)
327 return encoder_last_error_;
328
329 uint32_t frame_length =
330 media::VideoFrame::AllocationSize(media_format_, input_coded_size_);
331 uint32_t buffer_size = frame_length +
332 sizeof(ppapi::MediaStreamBuffer::Video) -
333 sizeof(ppapi::MediaStreamBuffer::Video::data);
334
335 // Make each buffer 4 byte aligned.
336 base::CheckedNumeric<int32_t> buffer_size_aligned = buffer_size;
337 buffer_size_aligned += (4 - buffer_size % 4);
338
339 base::CheckedNumeric<int32_t> total_size = frame_count_ * buffer_size_aligned;
340 if (!total_size.IsValid())
341 return PP_ERROR_FAILED;
342
343 // TODO(llandwerlin): HostAllocateSharedMemoryBuffer() is apparently
344 // synchronous and should be avoided.
345 scoped_ptr<base::SharedMemory> shm(
346 RenderThreadImpl::current()
347 ->HostAllocateSharedMemoryBuffer(total_size.ValueOrDie())
348 .Pass());
349 if (!shm)
350 return PP_ERROR_FAILED;
351
352 VLOG(4) << " frame_count=" << frame_count_ << " frame_length=" << frame_length
353 << " buffer_size=" << buffer_size_aligned.ValueOrDie();
354
355 if (!buffer_manager_->SetBuffers(
356 frame_count_, buffer_size_aligned.ValueOrDie(), shm.Pass(), true))
357 return PP_ERROR_FAILED;
358
359 for (int32_t i = 0; i < buffer_manager_->number_of_buffers(); ++i) {
360 ppapi::MediaStreamBuffer::Video* buffer =
361 &(buffer_manager_->GetBufferPointer(i)->video);
362 buffer->header.size = buffer_manager_->buffer_size();
363 buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO;
364 buffer->format = MediaToPepperVideoFormat(media_format_);
365 buffer->size.width = input_coded_size_.width();
366 buffer->size.height = input_coded_size_.height();
367 buffer->data_size = frame_length;
368 }
369
370 ppapi::host::ReplyMessageContext reply_context =
371 context->MakeReplyMessageContext();
372 reply_context.params.AppendHandle(SerializedHandle(
373 renderer_ppapi_host_->ShareHandleWithRemote(
374 ConvertSharedMemoryHandle(*buffer_manager_->shm()), false),
375 total_size.ValueOrDie()));
376
377 host()->SendReply(reply_context,
378 PpapiPluginMsg_VideoEncoder_GetVideoFramesReply(
379 frame_count_, buffer_size_aligned.ValueOrDie(),
380 PP_FromGfxSize(input_coded_size_)));
381
382 return PP_OK_COMPLETIONPENDING;
383 }
384
385 int32_t PepperVideoEncoderHost::OnHostMsgEncode(
386 ppapi::host::HostMessageContext* context,
387 uint32_t frame_id,
388 bool force_keyframe) {
389 if (encoder_last_error_)
390 return encoder_last_error_;
391
392 encoder_->Encode(
393 CreateVideoFrame(frame_id, context->MakeReplyMessageContext()),
394 force_keyframe);
395
396 return PP_OK_COMPLETIONPENDING;
397 }
398
399 int32_t PepperVideoEncoderHost::OnHostMsgRecycleBitstreamBuffer(
400 ppapi::host::HostMessageContext* context,
401 uint32_t buffer_id) {
402 if (encoder_last_error_)
403 return encoder_last_error_;
404
405 if (buffer_id < 0 || buffer_id >= buffers_.size() ||
406 buffers_[buffer_id]->in_use)
407 return PP_ERROR_BADARGUMENT;
408
409 buffers_[buffer_id]->in_use = true;
410 encoder_->UseOutputBitstreamBuffer(buffers_[buffer_id]->toBitstreamBuffer());
411
412 return PP_OK;
413 }
414
415 int32_t PepperVideoEncoderHost::OnHostMsgRequestEncodingParametersChange(
416 ppapi::host::HostMessageContext* context,
417 uint32_t bitrate,
418 uint32_t framerate) {
419 if (encoder_last_error_)
420 return encoder_last_error_;
421
422 encoder_->RequestEncodingParametersChange(bitrate, framerate);
423
424 return PP_OK;
425 }
426
427 int32_t PepperVideoEncoderHost::OnHostMsgClose(
428 ppapi::host::HostMessageContext* context) {
429 NotifyPepperError(PP_ERROR_ABORTED);
430
431 return PP_OK;
432 }
433
434 void PepperVideoEncoderHost::RequireBitstreamBuffers(
435 unsigned int frame_count,
436 const gfx::Size& input_coded_size,
437 size_t output_buffer_size) {
438 DCHECK(RenderThreadImpl::current());
439
440 buffers_.clear();
441 for (int32_t i = 0; i < kDefaultNumberOfBitstreamBuffers; ++i) {
442 scoped_ptr<base::SharedMemory> shm(
443 RenderThread::Get()
444 ->HostAllocateSharedMemoryBuffer(output_buffer_size)
445 .Pass());
446
447 if (!shm || !shm->Map(output_buffer_size)) {
448 buffers_.clear();
449 break;
450 }
451
452 buffers_.push_back(new ShmBuffer(i, shm.Pass(), output_buffer_size));
453
454 initialize_reply_context_.params.AppendHandle(
455 ppapi::proxy::SerializedHandle(
456 renderer_ppapi_host_->ShareHandleWithRemote(
457 ConvertSharedMemoryHandle(*buffers_.back()->shm), false),
458 output_buffer_size));
459 }
460
461 if (buffers_.empty()) {
462 NotifyPepperError(PP_ERROR_FAILED);
463 return;
464 }
465
466 // Feed buffers to the encoder.
467 for (size_t i = 0; i < buffers_.size(); ++i) {
468 encoder_->UseOutputBitstreamBuffer(buffers_[i]->toBitstreamBuffer());
469 }
470
471 // Notify the plugins of the buffers and the input size.
472 PP_Size size;
473 size.width = input_coded_size.width();
474 size.height = input_coded_size.height();
475 input_coded_size_ = input_coded_size;
476 frame_count_ = frame_count;
477 initialized_ = true;
478 encoder_last_error_ = PP_OK;
479
480 host()->SendReply(
481 initialize_reply_context_,
482 PpapiPluginMsg_VideoEncoder_InitializeReply(
483 buffers_.size(), output_buffer_size, frame_count, size));
484 }
485
486 void PepperVideoEncoderHost::BitstreamBufferReady(int32 buffer_id,
487 size_t payload_size,
488 bool key_frame) {
489 DCHECK(RenderThreadImpl::current());
490 DCHECK(buffers_[buffer_id]->in_use);
491
492 buffers_[buffer_id]->in_use = false;
493 host()->SendUnsolicitedReply(pp_resource(),
494 PpapiPluginMsg_VideoEncoder_BitstreamBufferReady(
495 buffer_id, payload_size, key_frame));
496 }
497
498 void PepperVideoEncoderHost::NotifyError(
499 media::VideoEncodeAccelerator::Error error) {
500 DCHECK(RenderThreadImpl::current());
501 NotifyPepperError(PP_FromMediaEncodeAcceleratorError(error));
502 }
503
504 scoped_refptr<media::VideoFrame> PepperVideoEncoderHost::CreateVideoFrame(
505 uint32_t frame_id,
506 const ppapi::host::ReplyMessageContext& reply_context) {
507 ppapi::MediaStreamBuffer* buffer =
508 buffer_manager_->GetBufferPointer(frame_id);
509
510 uint32_t shm_offset = frame_id * buffer_manager_->buffer_size() +
511 sizeof(ppapi::MediaStreamBuffer::Video) -
512 sizeof(ppapi::MediaStreamBuffer::Video::data);
513
514 return media::VideoFrame::WrapExternalPackedMemory(
515 media_format_, input_coded_size, gfx::Rect(input_coded_size_),
516 input_coded_size_, static_cast<uint8*>(buffer->video.data),
517 buffer->video.data_size, buffer_manager_->shm()->handle(), shm_offset,
518 base::TimeDelta(), base::Bind(
519 &PepperVideoEncoderHost::EncodeVideoFrameDone,
520 weak_ptr_factory_.GetWeakPtr(), base::Passed(shm.Pass()),
521 reply_context));
522 }
523
524 void PepperVideoEncoderHost::EncodeVideoFrameDone(
525 const ppapi::host::ReplyMessageContext& reply_context,
526 uint32_t frame_id) {
527 DCHECK(RenderThreadImpl::current());
528
529 ppapi::host::ReplyMessageContext context = reply_context;
530 context.params.set_result(encoder_last_error_);
531 host()->SendReply(reply_context,
532 PpapiPluginMsg_VideoEncoder_EncodeReply(frame_id));
533 }
534
535 void PepperVideoEncoderHost::NotifyPepperError(int32_t error) {
536 DCHECK(RenderThreadImpl::current());
537
538 encoder_last_error_ = error;
539 encoder_->Destroy();
540 base::Unretained(encoder_.release());
541 host()->SendUnsolicitedReply(
542 pp_resource(),
543 PpapiPluginMsg_VideoEncoder_NotifyError(encoder_last_error_));
544 }
545
546 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698