OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "webkit/plugins/ppapi/ppb_video_decoder_impl.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/metrics/histogram.h" | |
12 #include "gpu/command_buffer/client/gles2_implementation.h" | |
13 #include "media/video/picture.h" | |
14 #include "media/video/video_decode_accelerator.h" | |
15 #include "ppapi/c/dev/pp_video_dev.h" | |
16 #include "ppapi/c/dev/ppb_video_decoder_dev.h" | |
17 #include "ppapi/c/dev/ppp_video_decoder_dev.h" | |
18 #include "ppapi/c/pp_completion_callback.h" | |
19 #include "ppapi/c/pp_errors.h" | |
20 #include "ppapi/shared_impl/resource_tracker.h" | |
21 #include "ppapi/thunk/enter.h" | |
22 #include "webkit/plugins/ppapi/common.h" | |
23 #include "webkit/plugins/ppapi/plugin_module.h" | |
24 #include "webkit/plugins/ppapi/ppb_buffer_impl.h" | |
25 #include "webkit/plugins/ppapi/ppb_graphics_3d_impl.h" | |
26 #include "webkit/plugins/ppapi/resource_helper.h" | |
27 | |
28 using ppapi::TrackedCallback; | |
29 using ppapi::thunk::EnterResourceNoLock; | |
30 using ppapi::thunk::PPB_Buffer_API; | |
31 using ppapi::thunk::PPB_Graphics3D_API; | |
32 using ppapi::thunk::PPB_VideoDecoder_API; | |
33 | |
34 namespace { | |
35 | |
36 // Convert PP_VideoDecoder_Profile to media::VideoCodecProfile. | |
37 media::VideoCodecProfile PPToMediaProfile( | |
38 const PP_VideoDecoder_Profile pp_profile) { | |
39 switch (pp_profile) { | |
40 case PP_VIDEODECODER_H264PROFILE_NONE: | |
41 // HACK: PPAPI contains a bogus "none" h264 profile that doesn't | |
42 // correspond to anything in h.264; but a number of released chromium | |
43 // versions silently promoted this to Baseline profile, so we retain that | |
44 // behavior here. Fall through. | |
45 case PP_VIDEODECODER_H264PROFILE_BASELINE: | |
46 return media::H264PROFILE_BASELINE; | |
47 case PP_VIDEODECODER_H264PROFILE_MAIN: | |
48 return media::H264PROFILE_MAIN; | |
49 case PP_VIDEODECODER_H264PROFILE_EXTENDED: | |
50 return media::H264PROFILE_EXTENDED; | |
51 case PP_VIDEODECODER_H264PROFILE_HIGH: | |
52 return media::H264PROFILE_HIGH; | |
53 case PP_VIDEODECODER_H264PROFILE_HIGH10PROFILE: | |
54 return media::H264PROFILE_HIGH10PROFILE; | |
55 case PP_VIDEODECODER_H264PROFILE_HIGH422PROFILE: | |
56 return media::H264PROFILE_HIGH422PROFILE; | |
57 case PP_VIDEODECODER_H264PROFILE_HIGH444PREDICTIVEPROFILE: | |
58 return media::H264PROFILE_HIGH444PREDICTIVEPROFILE; | |
59 case PP_VIDEODECODER_H264PROFILE_SCALABLEBASELINE: | |
60 return media::H264PROFILE_SCALABLEBASELINE; | |
61 case PP_VIDEODECODER_H264PROFILE_SCALABLEHIGH: | |
62 return media::H264PROFILE_SCALABLEHIGH; | |
63 case PP_VIDEODECODER_H264PROFILE_STEREOHIGH: | |
64 return media::H264PROFILE_STEREOHIGH; | |
65 case PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH: | |
66 return media::H264PROFILE_MULTIVIEWHIGH; | |
67 case PP_VIDEODECODER_VP8PROFILE_MAIN: | |
68 return media::VP8PROFILE_MAIN; | |
69 default: | |
70 return media::VIDEO_CODEC_PROFILE_UNKNOWN; | |
71 } | |
72 } | |
73 | |
74 PP_VideoDecodeError_Dev MediaToPPError( | |
75 media::VideoDecodeAccelerator::Error error) { | |
76 switch (error) { | |
77 case media::VideoDecodeAccelerator::ILLEGAL_STATE : | |
78 return PP_VIDEODECODERERROR_ILLEGAL_STATE; | |
79 case media::VideoDecodeAccelerator::INVALID_ARGUMENT : | |
80 return PP_VIDEODECODERERROR_INVALID_ARGUMENT; | |
81 case media::VideoDecodeAccelerator::UNREADABLE_INPUT : | |
82 return PP_VIDEODECODERERROR_UNREADABLE_INPUT; | |
83 case media::VideoDecodeAccelerator::PLATFORM_FAILURE : | |
84 return PP_VIDEODECODERERROR_PLATFORM_FAILURE; | |
85 default: | |
86 NOTREACHED(); | |
87 return PP_VIDEODECODERERROR_ILLEGAL_STATE; | |
88 } | |
89 } | |
90 | |
91 } // namespace | |
92 | |
93 namespace webkit { | |
94 namespace ppapi { | |
95 | |
96 PPB_VideoDecoder_Impl::PPB_VideoDecoder_Impl(PP_Instance instance) | |
97 : PPB_VideoDecoder_Shared(instance), | |
98 ppp_videodecoder_(NULL) { | |
99 PluginModule* plugin_module = ResourceHelper::GetPluginModule(this); | |
100 if (plugin_module) { | |
101 ppp_videodecoder_ = static_cast<const PPP_VideoDecoder_Dev*>( | |
102 plugin_module->GetPluginInterface(PPP_VIDEODECODER_DEV_INTERFACE)); | |
103 } | |
104 } | |
105 | |
106 PPB_VideoDecoder_Impl::~PPB_VideoDecoder_Impl() { | |
107 Destroy(); | |
108 } | |
109 | |
110 // static | |
111 PP_Resource PPB_VideoDecoder_Impl::Create( | |
112 PP_Instance instance, | |
113 PP_Resource graphics_context, | |
114 PP_VideoDecoder_Profile profile) { | |
115 EnterResourceNoLock<PPB_Graphics3D_API> enter_context(graphics_context, true); | |
116 if (enter_context.failed()) | |
117 return 0; | |
118 PPB_Graphics3D_Impl* graphics3d_impl = | |
119 static_cast<PPB_Graphics3D_Impl*>(enter_context.object()); | |
120 | |
121 scoped_refptr<PPB_VideoDecoder_Impl> decoder( | |
122 new PPB_VideoDecoder_Impl(instance)); | |
123 if (decoder->Init(graphics_context, graphics3d_impl->platform_context(), | |
124 graphics3d_impl->gles2_impl(), profile)) | |
125 return decoder->GetReference(); | |
126 return 0; | |
127 } | |
128 | |
129 bool PPB_VideoDecoder_Impl::Init( | |
130 PP_Resource graphics_context, | |
131 PluginDelegate::PlatformContext3D* context, | |
132 gpu::gles2::GLES2Implementation* gles2_impl, | |
133 PP_VideoDecoder_Profile profile) { | |
134 InitCommon(graphics_context, gles2_impl); | |
135 | |
136 int command_buffer_route_id = context->GetCommandBufferRouteId(); | |
137 if (command_buffer_route_id == 0) | |
138 return false; | |
139 | |
140 PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(this); | |
141 if (!plugin_delegate) | |
142 return false; | |
143 | |
144 platform_video_decoder_.reset(plugin_delegate->CreateVideoDecoder( | |
145 this, command_buffer_route_id)); | |
146 if (!platform_video_decoder_) | |
147 return false; | |
148 | |
149 FlushCommandBuffer(); | |
150 return platform_video_decoder_->Initialize(PPToMediaProfile(profile)); | |
151 } | |
152 | |
153 int32_t PPB_VideoDecoder_Impl::Decode( | |
154 const PP_VideoBitstreamBuffer_Dev* bitstream_buffer, | |
155 scoped_refptr<TrackedCallback> callback) { | |
156 if (!platform_video_decoder_) | |
157 return PP_ERROR_BADRESOURCE; | |
158 | |
159 EnterResourceNoLock<PPB_Buffer_API> enter(bitstream_buffer->data, true); | |
160 if (enter.failed()) | |
161 return PP_ERROR_FAILED; | |
162 | |
163 PPB_Buffer_Impl* buffer = static_cast<PPB_Buffer_Impl*>(enter.object()); | |
164 DCHECK_GE(bitstream_buffer->id, 0); | |
165 media::BitstreamBuffer decode_buffer( | |
166 bitstream_buffer->id, | |
167 buffer->shared_memory()->handle(), | |
168 bitstream_buffer->size); | |
169 if (!SetBitstreamBufferCallback(bitstream_buffer->id, callback)) | |
170 return PP_ERROR_BADARGUMENT; | |
171 | |
172 FlushCommandBuffer(); | |
173 platform_video_decoder_->Decode(decode_buffer); | |
174 return PP_OK_COMPLETIONPENDING; | |
175 } | |
176 | |
177 void PPB_VideoDecoder_Impl::AssignPictureBuffers( | |
178 uint32_t no_of_buffers, | |
179 const PP_PictureBuffer_Dev* buffers) { | |
180 if (!platform_video_decoder_) | |
181 return; | |
182 UMA_HISTOGRAM_COUNTS_100("Media.PepperVideoDecoderPictureCount", | |
183 no_of_buffers); | |
184 | |
185 std::vector<media::PictureBuffer> wrapped_buffers; | |
186 for (uint32 i = 0; i < no_of_buffers; i++) { | |
187 PP_PictureBuffer_Dev in_buf = buffers[i]; | |
188 DCHECK_GE(in_buf.id, 0); | |
189 media::PictureBuffer buffer( | |
190 in_buf.id, | |
191 gfx::Size(in_buf.size.width, in_buf.size.height), | |
192 in_buf.texture_id); | |
193 wrapped_buffers.push_back(buffer); | |
194 UMA_HISTOGRAM_COUNTS_10000("Media.PepperVideoDecoderPictureHeight", | |
195 in_buf.size.height); | |
196 } | |
197 | |
198 FlushCommandBuffer(); | |
199 platform_video_decoder_->AssignPictureBuffers(wrapped_buffers); | |
200 } | |
201 | |
202 void PPB_VideoDecoder_Impl::ReusePictureBuffer(int32_t picture_buffer_id) { | |
203 if (!platform_video_decoder_) | |
204 return; | |
205 | |
206 FlushCommandBuffer(); | |
207 platform_video_decoder_->ReusePictureBuffer(picture_buffer_id); | |
208 } | |
209 | |
210 int32_t PPB_VideoDecoder_Impl::Flush(scoped_refptr<TrackedCallback> callback) { | |
211 if (!platform_video_decoder_) | |
212 return PP_ERROR_BADRESOURCE; | |
213 | |
214 if (!SetFlushCallback(callback)) | |
215 return PP_ERROR_INPROGRESS; | |
216 | |
217 FlushCommandBuffer(); | |
218 platform_video_decoder_->Flush(); | |
219 return PP_OK_COMPLETIONPENDING; | |
220 } | |
221 | |
222 int32_t PPB_VideoDecoder_Impl::Reset(scoped_refptr<TrackedCallback> callback) { | |
223 if (!platform_video_decoder_) | |
224 return PP_ERROR_BADRESOURCE; | |
225 | |
226 if (!SetResetCallback(callback)) | |
227 return PP_ERROR_INPROGRESS; | |
228 | |
229 FlushCommandBuffer(); | |
230 platform_video_decoder_->Reset(); | |
231 return PP_OK_COMPLETIONPENDING; | |
232 } | |
233 | |
234 void PPB_VideoDecoder_Impl::Destroy() { | |
235 FlushCommandBuffer(); | |
236 | |
237 if (platform_video_decoder_) | |
238 platform_video_decoder_.release()->Destroy(); | |
239 ppp_videodecoder_ = NULL; | |
240 | |
241 ::ppapi::PPB_VideoDecoder_Shared::Destroy(); | |
242 } | |
243 | |
244 void PPB_VideoDecoder_Impl::ProvidePictureBuffers( | |
245 uint32 requested_num_of_buffers, | |
246 const gfx::Size& dimensions, | |
247 uint32 texture_target) { | |
248 if (!ppp_videodecoder_) | |
249 return; | |
250 | |
251 PP_Size out_dim = PP_MakeSize(dimensions.width(), dimensions.height()); | |
252 ppp_videodecoder_->ProvidePictureBuffers(pp_instance(), pp_resource(), | |
253 requested_num_of_buffers, &out_dim, texture_target); | |
254 } | |
255 | |
256 void PPB_VideoDecoder_Impl::PictureReady(const media::Picture& picture) { | |
257 if (!ppp_videodecoder_) | |
258 return; | |
259 | |
260 PP_Picture_Dev output; | |
261 output.picture_buffer_id = picture.picture_buffer_id(); | |
262 output.bitstream_buffer_id = picture.bitstream_buffer_id(); | |
263 ppp_videodecoder_->PictureReady(pp_instance(), pp_resource(), &output); | |
264 } | |
265 | |
266 void PPB_VideoDecoder_Impl::DismissPictureBuffer(int32 picture_buffer_id) { | |
267 if (!ppp_videodecoder_) | |
268 return; | |
269 ppp_videodecoder_->DismissPictureBuffer(pp_instance(), pp_resource(), | |
270 picture_buffer_id); | |
271 } | |
272 | |
273 void PPB_VideoDecoder_Impl::NotifyError( | |
274 media::VideoDecodeAccelerator::Error error) { | |
275 if (!ppp_videodecoder_) | |
276 return; | |
277 | |
278 PP_VideoDecodeError_Dev pp_error = MediaToPPError(error); | |
279 ppp_videodecoder_->NotifyError(pp_instance(), pp_resource(), pp_error); | |
280 UMA_HISTOGRAM_ENUMERATION( | |
281 "Media.PepperVideoDecoderError", error, | |
282 media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM); | |
283 } | |
284 | |
285 void PPB_VideoDecoder_Impl::NotifyResetDone() { | |
286 RunResetCallback(PP_OK); | |
287 } | |
288 | |
289 void PPB_VideoDecoder_Impl::NotifyEndOfBitstreamBuffer( | |
290 int32 bitstream_buffer_id) { | |
291 RunBitstreamBufferCallback(bitstream_buffer_id, PP_OK); | |
292 } | |
293 | |
294 void PPB_VideoDecoder_Impl::NotifyFlushDone() { | |
295 RunFlushCallback(PP_OK); | |
296 } | |
297 | |
298 void PPB_VideoDecoder_Impl::NotifyInitializeDone() { | |
299 NOTREACHED() << "PlatformVideoDecoder::Initialize() is synchronous!"; | |
300 } | |
301 | |
302 } // namespace ppapi | |
303 } // namespace webkit | |
OLD | NEW |