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

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

Issue 270213004: Implement Pepper PPB_VideoDecoder interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014 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 "content/renderer/pepper/pepper_video_decoder_host.h"
6
7 #include "base/bind.h"
8 #include "base/memory/shared_memory.h"
9 #include "content/common/gpu/client/gpu_channel_host.h"
10 #include "content/public/renderer/render_thread.h"
11 #include "content/public/renderer/renderer_ppapi_host.h"
12 #include "content/renderer/pepper/ppb_graphics_3d_impl.h"
13 #include "content/renderer/render_thread_impl.h"
14 #include "content/renderer/render_view_impl.h"
15 #include "gpu/command_buffer/client/gles2_implementation.h"
16 #include "media/video/picture.h"
17 #include "media/video/video_decode_accelerator.h"
18 #include "ppapi/c/pp_completion_callback.h"
19 #include "ppapi/c/pp_errors.h"
20 #include "ppapi/host/dispatch_host_message.h"
21 #include "ppapi/host/ppapi_host.h"
22 #include "ppapi/proxy/ppapi_messages.h"
23 #include "ppapi/thunk/enter.h"
24 #include "ppapi/thunk/ppb_graphics_3d_api.h"
25
26 using ppapi::proxy::SerializedHandle;
27 using ppapi::thunk::EnterResourceNoLock;
28 using ppapi::thunk::PPB_Graphics3D_API;
29
30 namespace content {
31
32 namespace {
33
34 #define COMPILE_ASSERT_MATCHING_ENUM(media_name, np_name) \
35 COMPILE_ASSERT( \
36 static_cast<int>(media::media_name) == static_cast<int>(np_name), \
37 mismatching_enums)
38
39 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_BASELINE,
40 PP_VIDEOPROFILE_H264BASELINE);
41 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_MAIN, PP_VIDEOPROFILE_H264MAIN);
42 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_EXTENDED,
43 PP_VIDEOPROFILE_H264EXTENDED);
44 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_HIGH, PP_VIDEOPROFILE_H264HIGH);
45 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_HIGH10PROFILE,
46 PP_VIDEOPROFILE_H264HIGH10PROFILE);
47 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_HIGH422PROFILE,
48 PP_VIDEOPROFILE_H264HIGH422PROFILE);
49 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_HIGH444PREDICTIVEPROFILE,
50 PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE);
51 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_SCALABLEBASELINE,
52 PP_VIDEOPROFILE_H264SCALABLEBASELINE);
53 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_SCALABLEHIGH,
54 PP_VIDEOPROFILE_H264SCALABLEHIGH);
55 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_STEREOHIGH,
56 PP_VIDEOPROFILE_H264STEREOHIGH);
57 COMPILE_ASSERT_MATCHING_ENUM(H264PROFILE_MULTIVIEWHIGH,
58 PP_VIDEOPROFILE_H264MULTIVIEWHIGH);
59 COMPILE_ASSERT_MATCHING_ENUM(VP8PROFILE_MAIN, PP_VIDEOPROFILE_VP8MAIN);
60
61 } // namespace
62
63 PepperVideoDecoderHost::PepperVideoDecoderHost(RendererPpapiHost* host,
64 PP_Instance instance,
65 PP_Resource resource)
66 : ResourceHost(host->GetPpapiHost(), instance, resource),
67 renderer_ppapi_host_(host),
68 initialized_(false),
69 weak_factory_(this) {
70 }
71
72 PepperVideoDecoderHost::~PepperVideoDecoderHost() {
73 if (decoder_) {
74 decoder_->Destroy();
75 decoder_.reset();
76 }
77 }
78
79 int32_t PepperVideoDecoderHost::OnResourceMessageReceived(
80 const IPC::Message& msg,
81 ppapi::host::HostMessageContext* context) {
82 IPC_BEGIN_MESSAGE_MAP(PepperVideoDecoderHost, msg)
83 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Initialize,
Tom Sepez 2014/05/08 20:35:07 nit: it's common to indent these two spaces betwee
bbudge 2014/05/14 16:40:41 We're trying to use clang-format on Pepper code. I
84 OnHostMsgInitialize)
85 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_GetShm,
86 OnHostMsgGetShm)
87 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_AssignTextures,
88 OnHostMsgAssignTextures)
89 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_Decode,
90 OnHostMsgDecode)
91 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_VideoDecoder_RecyclePicture,
92 OnHostMsgRecyclePicture)
93 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Flush,
94 OnHostMsgFlush)
95 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_VideoDecoder_Reset,
96 OnHostMsgReset)
97 IPC_END_MESSAGE_MAP()
98 return PP_ERROR_FAILED;
99 }
100
101 int32_t PepperVideoDecoderHost::OnHostMsgInitialize(
102 ppapi::host::HostMessageContext* context,
103 ppapi::HostResource graphics_context,
104 PP_VideoProfile profile,
105 bool allow_software_fallback) {
106 if (initialized_)
107 return PP_ERROR_FAILED;
108 if (profile < 0 || profile > PP_VIDEOPROFILE_MAX)
dmichael (off chromium) 2014/05/08 20:27:00 Should that be >= PP_VIDEOPROFILE_MAX? It looks l
bbudge 2014/05/14 16:40:41 There should be no more VP9 in the API. It isn't s
109 return PP_ERROR_BADARGUMENT;
110
111 EnterResourceNoLock<PPB_Graphics3D_API> enter(
112 graphics_context.host_resource(), true);
113 if (enter.failed())
114 return PP_ERROR_BADRESOURCE;
115 PPB_Graphics3D_Impl* graphics3d_impl =
116 static_cast<PPB_Graphics3D_Impl*>(enter.object());
117 int command_buffer_route_id = graphics3d_impl->GetCommandBufferRouteId();
118 if (!command_buffer_route_id)
119 return PP_ERROR_FAILED;
120
121 media::VideoCodecProfile media_profile =
122 static_cast<media::VideoCodecProfile>(profile);
123
124 // This is not synchronous, but subsequent IPC messages will be buffered, so
125 // it is okay to immediately send IPC messages through the returned channel.
126 GpuChannelHost* channel = graphics3d_impl->channel();
127 DCHECK(channel);
128
129 if (channel) {
130 decoder_ = channel->CreateVideoDecoder(command_buffer_route_id);
131 if (decoder_ && decoder_->Initialize(media_profile, this)) {
132 initialized_ = true;
133 return PP_OK;
134 }
135 decoder_.reset();
136 }
137
138 // TODO(bbudge) Implement software fallback.
139 return PP_ERROR_NOTSUPPORTED;
140 }
141
142 int32_t PepperVideoDecoderHost::OnHostMsgGetShm(
143 ppapi::host::HostMessageContext* context,
144 uint32_t size) {
145 if (!initialized_)
146 return PP_ERROR_FAILED;
147
148 content::RenderThread* render_thread = content::RenderThread::Get();
149 scoped_ptr<base::SharedMemory> shm(
150 render_thread->HostAllocateSharedMemoryBuffer(size).Pass());
151 if (!shm)
152 return PP_ERROR_FAILED;
153 if (!shm->Map(size))
154 return PP_ERROR_FAILED;
155
156 base::SharedMemoryHandle shm_handle = shm->handle();
157 shm_buffers_.push_back(shm.release());
158
159 base::PlatformFile platform_file =
160 #if defined(OS_WIN)
161 shm_handle;
162 #elif defined(OS_POSIX)
163 shm_handle.fd;
164 #else
165 #error Not implemented.
166 #endif
167 SerializedHandle handle(
168 renderer_ppapi_host_->ShareHandleWithRemote(platform_file, false), size);
169 ppapi::host::ReplyMessageContext reply_context =
170 context->MakeReplyMessageContext();
171 reply_context.params.AppendHandle(handle);
172 host()->SendReply(reply_context,
173 PpapiPluginMsg_VideoDecoder_GetShmReply(size));
174 return PP_OK_COMPLETIONPENDING;
175 }
176
177 int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures(
178 ppapi::host::HostMessageContext* context,
179 PP_Size size,
180 const std::vector<uint32_t>& texture_ids) {
181 if (!initialized_)
182 return PP_ERROR_FAILED;
183
184 DCHECK(decoder_);
185 if (decoder_) {
dmichael (off chromium) 2014/05/08 20:27:00 nit: What's inside the if block is actually the co
bbudge 2014/05/14 16:40:41 Much better. Done.
186 std::vector<media::PictureBuffer> picture_buffers;
187 for (uint32 i = 0; i < texture_ids.size(); i++) {
188 media::PictureBuffer buffer(
189 texture_ids[i], // Use the texture_id to identify the buffer.
190 gfx::Size(size.width, size.height),
191 texture_ids[i]);
192 picture_buffers.push_back(buffer);
193 }
194 decoder_->AssignPictureBuffers(picture_buffers);
195 }
196 return PP_OK;
197 }
198
199 int32_t PepperVideoDecoderHost::OnHostMsgDecode(
200 ppapi::host::HostMessageContext* context,
201 uint32_t shm_id,
202 uint32_t size) {
203 if (!initialized_)
204 return PP_ERROR_FAILED;
205 // |shm_id| is just an index into shm_buffers_. Make sure it's in range.
206 if (static_cast<size_t>(shm_id) >= shm_buffers_.size())
207 return PP_ERROR_FAILED;
208
209 pending_decodes_.insert(
210 std::make_pair(shm_id, context->MakeReplyMessageContext()));
211
212 base::SharedMemory* shm = shm_buffers_[shm_id];
213 DCHECK(decoder_);
214 if (decoder_)
215 decoder_->Decode(media::BitstreamBuffer(shm_id, shm->handle(), size));
216
217 return PP_OK_COMPLETIONPENDING;
218 }
219
220 int32_t PepperVideoDecoderHost::OnHostMsgRecyclePicture(
221 ppapi::host::HostMessageContext* context,
222 uint32_t texture_id) {
223 if (!initialized_)
224 return PP_ERROR_FAILED;
225 DCHECK(decoder_);
226 if (decoder_)
227 decoder_->ReusePictureBuffer(texture_id);
228
229 return PP_OK;
230 }
231
232 int32_t PepperVideoDecoderHost::OnHostMsgFlush(
233 ppapi::host::HostMessageContext* context) {
234 if (!initialized_)
235 return PP_ERROR_FAILED;
236
237 flush_reply_context_ = context->MakeReplyMessageContext();
238 DCHECK(decoder_);
239 if (decoder_)
240 decoder_->Flush();
241
242 return PP_OK_COMPLETIONPENDING;
243 }
244
245 int32_t PepperVideoDecoderHost::OnHostMsgReset(
246 ppapi::host::HostMessageContext* context) {
247 if (!initialized_)
248 return PP_ERROR_FAILED;
249
250 reset_reply_context_ = context->MakeReplyMessageContext();
251 DCHECK(decoder_);
252 if (decoder_)
253 decoder_->Reset();
254
255 return PP_OK_COMPLETIONPENDING;
256 }
257
258 void PepperVideoDecoderHost::ProvidePictureBuffers(
259 uint32 requested_num_of_buffers,
260 const gfx::Size& dimensions,
261 uint32 texture_target) {
262 RequestTextures(requested_num_of_buffers,
263 dimensions,
264 texture_target,
265 std::vector<gpu::Mailbox>());
266 }
267
268 void PepperVideoDecoderHost::RequestTextures(
269 uint32 requested_num_of_buffers,
270 const gfx::Size& dimensions,
271 uint32 texture_target,
272 const std::vector<gpu::Mailbox>& mailboxes) {
dmichael (off chromium) 2014/05/08 20:27:00 I don't see any case where mailboxes will be anyth
bbudge 2014/05/14 16:40:41 Removed these for now.
273 DCHECK(RenderThreadImpl::current());
274 host()->SendUnsolicitedReply(
275 pp_resource(),
276 PpapiPluginMsg_VideoDecoder_RequestTextures(
277 requested_num_of_buffers,
278 PP_MakeSize(dimensions.width(), dimensions.height()),
279 texture_target,
280 mailboxes));
281 }
282
283 void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) {
284 DCHECK(RenderThreadImpl::current());
285 host()->SendUnsolicitedReply(
286 pp_resource(),
287 PpapiPluginMsg_VideoDecoder_PictureReady(picture.bitstream_buffer_id(),
288 picture.picture_buffer_id()));
289 }
290
291 void PepperVideoDecoderHost::DismissPictureBuffer(int32 picture_buffer_id) {
292 DCHECK(RenderThreadImpl::current());
293 host()->SendUnsolicitedReply(
294 pp_resource(),
295 PpapiPluginMsg_VideoDecoder_DismissPicture(picture_buffer_id));
296 }
297
298 void PepperVideoDecoderHost::NotifyError(
299 media::VideoDecodeAccelerator::Error error) {
300 DCHECK(RenderThreadImpl::current());
301 int32_t pp_error = PP_ERROR_FAILED;
302 switch (error) {
303 case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
304 pp_error = PP_ERROR_UNREADABLE_INPUT;
305 break;
306 case media::VideoDecodeAccelerator::ILLEGAL_STATE:
307 case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
308 case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
309 pp_error = PP_ERROR_PLATFORM_FAILED;
310 break;
311 default:
312 NOTREACHED();
313 break;
314 }
315 host()->SendUnsolicitedReply(
316 pp_resource(), PpapiPluginMsg_VideoDecoder_NotifyError(pp_error));
317 }
318
319 void PepperVideoDecoderHost::NotifyResetDone() {
320 DCHECK(RenderThreadImpl::current());
321 host()->SendReply(reset_reply_context_,
322 PpapiPluginMsg_VideoDecoder_ResetReply());
323 reset_reply_context_ = ppapi::host::ReplyMessageContext();
324 }
325
326 void PepperVideoDecoderHost::NotifyEndOfBitstreamBuffer(
327 int32 bitstream_buffer_id) {
328 DCHECK(RenderThreadImpl::current());
329 uint32_t shm_id = static_cast<uint32_t>(bitstream_buffer_id);
330 ReplyMap::iterator it = pending_decodes_.find(shm_id);
331 DCHECK(it != pending_decodes_.end());
Tom Sepez 2014/05/08 20:35:07 Can this happen for real? Does bitstream_buffer_i
bbudge 2014/05/14 16:40:41 This is from the decoder which is trusted. A futur
332 host()->SendReply(it->second,
333 PpapiPluginMsg_VideoDecoder_DecodeReply(shm_id));
334
335 pending_decodes_.erase(it);
336 }
337
338 void PepperVideoDecoderHost::NotifyFlushDone() {
339 DCHECK(RenderThreadImpl::current());
340 host()->SendReply(flush_reply_context_,
341 PpapiPluginMsg_VideoDecoder_FlushReply());
342 flush_reply_context_ = ppapi::host::ReplyMessageContext();
343 }
344
345 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698