OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 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 <GLES2/gl2.h> | |
6 | |
7 #include "base/memory/shared_memory.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "ppapi/c/pp_errors.h" | |
10 #include "ppapi/c/ppb_video_decoder.h" | |
11 #include "ppapi/proxy/locking_resource_releaser.h" | |
12 #include "ppapi/proxy/plugin_message_filter.h" | |
13 #include "ppapi/proxy/ppapi_message_utils.h" | |
14 #include "ppapi/proxy/ppapi_messages.h" | |
15 #include "ppapi/proxy/ppapi_proxy_test.h" | |
16 #include "ppapi/proxy/ppb_graphics_3d_proxy.h" | |
17 #include "ppapi/proxy/video_decoder_constants.h" | |
18 #include "ppapi/proxy/video_decoder_resource.h" | |
19 #include "ppapi/shared_impl/proxy_lock.h" | |
20 #include "ppapi/thunk/thunk.h" | |
21 | |
22 using ppapi::proxy::ResourceMessageTestSink; | |
23 | |
24 namespace ppapi { | |
25 namespace proxy { | |
26 | |
27 namespace { | |
28 | |
29 const PP_Bool kAllowSoftwareFallback = PP_TRUE; | |
30 const PP_Resource kGraphics3D = 7; | |
31 const uint32_t kShmSize = 256; | |
32 const size_t kDecodeBufferSize = 16; | |
33 const uint32_t kDecodeId = 5; | |
34 const uint32_t kTextureId1 = 1; | |
35 const uint32_t kTextureId2 = 2; | |
36 const uint32_t kNumRequestedTextures = 2; | |
37 | |
38 class MockCompletionCallback { | |
39 public: | |
40 MockCompletionCallback() : called_(false) {} | |
41 | |
42 bool called() { return called_; } | |
43 int32_t result() { return result_; } | |
44 | |
45 void Reset() { called_ = false; } | |
46 | |
47 static void Callback(void* user_data, int32_t result) { | |
48 MockCompletionCallback* that = | |
49 reinterpret_cast<MockCompletionCallback*>(user_data); | |
50 that->called_ = true; | |
51 that->result_ = result; | |
52 } | |
53 | |
54 private: | |
55 bool called_; | |
56 int32_t result_; | |
57 }; | |
58 | |
59 class VideoDecoderResourceTest : public PluginProxyTest { | |
Ami GONE FROM CHROMIUM
2014/05/28 20:50:56
Only skimmed this file; hopefully other reviewers
bbudge
2014/05/29 00:03:34
Me too. I plan to add some browser_tests when we h
| |
60 public: | |
61 VideoDecoderResourceTest() | |
62 : decoder_iface_(thunk::GetPPB_VideoDecoder_0_1_Thunk()) {} | |
63 | |
64 const PPB_VideoDecoder_0_1* decoder_iface() const { return decoder_iface_; } | |
65 | |
66 void SendReply(const ResourceMessageCallParams& params, | |
67 int32_t result, | |
68 const IPC::Message& nested_message) { | |
69 ResourceMessageReplyParams reply_params(params.pp_resource(), | |
70 params.sequence()); | |
71 reply_params.set_result(result); | |
72 PluginMessageFilter::DispatchResourceReplyForTest(reply_params, | |
73 nested_message); | |
74 } | |
75 | |
76 void SendReplyWithHandle(const ResourceMessageCallParams& params, | |
77 int32_t result, | |
78 const IPC::Message& nested_message, | |
79 const SerializedHandle& handle) { | |
80 ResourceMessageReplyParams reply_params(params.pp_resource(), | |
81 params.sequence()); | |
82 reply_params.set_result(result); | |
83 reply_params.AppendHandle(handle); | |
84 PluginMessageFilter::DispatchResourceReplyForTest(reply_params, | |
85 nested_message); | |
86 } | |
87 | |
88 PP_Resource CreateDecoder() { | |
89 PP_Resource result = decoder_iface()->Create(pp_instance()); | |
90 if (result) { | |
91 ProxyAutoLock lock; | |
92 ppapi::Resource* resource = | |
93 GetGlobals()->GetResourceTracker()->GetResource(result); | |
94 proxy::VideoDecoderResource* decoder = | |
95 static_cast<proxy::VideoDecoderResource*>(resource); | |
96 decoder->SetForTest(); | |
97 } | |
98 | |
99 return result; | |
100 } | |
101 | |
102 PP_Resource CreateGraphics3d() { | |
103 ProxyAutoLock lock; | |
104 | |
105 HostResource host_resource; | |
106 host_resource.SetHostResource(pp_instance(), kGraphics3D); | |
107 scoped_refptr<ppapi::proxy::Graphics3D> graphics_3d( | |
108 new ppapi::proxy::Graphics3D(host_resource)); | |
109 return graphics_3d->GetReference(); | |
110 } | |
111 | |
112 PP_Resource CreateAndInitializeDecoder() { | |
113 PP_Resource decoder = CreateDecoder(); | |
114 LockingResourceReleaser graphics3d(CreateGraphics3d()); | |
115 MockCompletionCallback cb; | |
116 int32_t result = decoder_iface()->Initialize( | |
117 decoder, | |
118 graphics3d.get(), | |
119 PP_VIDEOPROFILE_H264MAIN, | |
120 PP_TRUE /* allow_software_fallback */, | |
121 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, | |
122 &cb)); | |
123 if (result != PP_OK_COMPLETIONPENDING) | |
124 return 0; | |
125 ResourceMessageCallParams params; | |
126 IPC::Message msg; | |
127 if (!sink().GetFirstResourceCallMatching( | |
128 PpapiHostMsg_VideoDecoder_Initialize::ID, ¶ms, &msg)) | |
129 return 0; | |
130 sink().ClearMessages(); | |
131 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_InitializeReply()); | |
132 return decoder; | |
133 } | |
134 | |
135 SerializedHandle CreateSharedMemory(uint32_t size) { | |
136 base::SharedMemory shm; | |
137 shm.CreateAnonymous(size); | |
138 base::SharedMemoryHandle shm_handle; | |
139 shm.ShareToProcess(base::GetCurrentProcessHandle(), &shm_handle); | |
140 return SerializedHandle(shm_handle, size); | |
141 } | |
142 | |
143 int32_t CallDecode(PP_Resource pp_decoder, | |
144 MockCompletionCallback* cb, | |
145 const PpapiHostMsg_VideoDecoder_GetShm* expected_shm_msg) { | |
146 // Set up a handler in case the resource sends a sync message to create | |
147 // shared memory. | |
148 ResourceSyncCallHandler shm_msg_handler( | |
149 &sink(), PpapiHostMsg_VideoDecoder_GetShm::ID, PP_OK, | |
150 PpapiPluginMsg_VideoDecoder_GetShmReply(kShmSize)); | |
151 sink().AddFilter(&shm_msg_handler); | |
152 | |
153 if (expected_shm_msg) { | |
154 base::SharedMemory shm; | |
155 shm.CreateAnonymous(kShmSize); | |
156 base::SharedMemoryHandle shm_handle; | |
157 shm.ShareToProcess(base::GetCurrentProcessHandle(), &shm_handle); | |
158 SerializedHandle serialized_handle(shm_handle, kShmSize); | |
159 shm_msg_handler.set_serialized_handle(&serialized_handle); | |
160 } | |
161 | |
162 memset(decode_buffer_, 0x55, kDecodeBufferSize); | |
163 int32_t result = | |
164 decoder_iface()->Decode(pp_decoder, | |
165 kDecodeId, | |
166 kDecodeBufferSize, | |
167 decode_buffer_, | |
168 PP_MakeOptionalCompletionCallback( | |
169 &MockCompletionCallback::Callback, cb)); | |
170 | |
171 if (expected_shm_msg) { | |
172 uint32_t shm_id, shm_size, expected_shm_id, expected_shm_size; | |
173 UnpackMessage<PpapiHostMsg_VideoDecoder_GetShm>( | |
174 *expected_shm_msg, &expected_shm_id, &expected_shm_size); | |
175 if (shm_msg_handler.last_handled_msg().type() == 0 || | |
176 !UnpackMessage<PpapiHostMsg_VideoDecoder_GetShm>( | |
177 shm_msg_handler.last_handled_msg(), &shm_id, &shm_size) || | |
178 shm_id != expected_shm_id || | |
179 shm_size != expected_shm_size) { | |
180 // Signal that the expected shm message wasn't sent by failing. | |
181 result = PP_ERROR_FAILED; | |
182 } | |
183 } | |
184 | |
185 sink().RemoveFilter(&shm_msg_handler); | |
186 return result; | |
187 } | |
188 | |
189 int32_t CallGetPicture(PP_Resource pp_decoder, | |
190 PP_VideoPicture* picture, | |
191 MockCompletionCallback* cb) { | |
192 int32_t result = | |
193 decoder_iface()->GetPicture(pp_decoder, | |
194 picture, | |
195 PP_MakeOptionalCompletionCallback( | |
196 &MockCompletionCallback::Callback, cb)); | |
197 return result; | |
198 } | |
199 | |
200 void CallRecyclePicture(PP_Resource pp_decoder, | |
201 const PP_VideoPicture& picture) { | |
202 decoder_iface()->RecyclePicture(pp_decoder, &picture); | |
203 } | |
204 | |
205 int32_t CallFlush(PP_Resource pp_decoder, MockCompletionCallback* cb) { | |
206 int32_t result = | |
207 decoder_iface()->Flush(pp_decoder, | |
208 PP_MakeOptionalCompletionCallback( | |
209 &MockCompletionCallback::Callback, cb)); | |
210 return result; | |
211 } | |
212 | |
213 int32_t CallReset(PP_Resource pp_decoder, MockCompletionCallback* cb) { | |
214 int32_t result = | |
215 decoder_iface()->Reset(pp_decoder, | |
216 PP_MakeOptionalCompletionCallback( | |
217 &MockCompletionCallback::Callback, cb)); | |
218 return result; | |
219 } | |
220 | |
221 void SendDecodeReply(const ResourceMessageCallParams& params, | |
222 uint32_t shm_id) { | |
223 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_DecodeReply(shm_id)); | |
224 } | |
225 | |
226 void SendPictureReady(const ResourceMessageCallParams& params, | |
227 uint32_t decode_count, | |
228 uint32_t texture_id) { | |
229 SendReply( | |
230 params, | |
231 PP_OK, | |
232 PpapiPluginMsg_VideoDecoder_PictureReady(decode_count, texture_id)); | |
233 } | |
234 | |
235 void SendFlushReply(const ResourceMessageCallParams& params) { | |
236 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_FlushReply()); | |
237 } | |
238 | |
239 void SendResetReply(const ResourceMessageCallParams& params) { | |
240 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_ResetReply()); | |
241 } | |
242 | |
243 void SendRequestTextures(const ResourceMessageCallParams& params) { | |
244 SendReply(params, | |
245 PP_OK, | |
246 PpapiPluginMsg_VideoDecoder_RequestTextures( | |
247 kNumRequestedTextures, PP_MakeSize(320, 240), GL_TEXTURE_2D)); | |
248 } | |
249 | |
250 void SendNotifyError(const ResourceMessageCallParams& params, int32_t error) { | |
251 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_NotifyError(error)); | |
252 } | |
253 | |
254 bool CheckDecodeMsg(ResourceMessageCallParams* params, | |
255 uint32_t* shm_id, | |
256 uint32_t* size) { | |
257 IPC::Message msg; | |
258 if (!sink().GetFirstResourceCallMatching( | |
259 PpapiHostMsg_VideoDecoder_Decode::ID, params, &msg)) | |
260 return false; | |
261 sink().ClearMessages(); | |
262 return UnpackMessage<PpapiHostMsg_VideoDecoder_Decode>(msg, shm_id, size); | |
263 } | |
264 | |
265 bool CheckRecyclePictureMsg(ResourceMessageCallParams* params, | |
266 uint32_t* texture_id) { | |
267 IPC::Message msg; | |
268 if (!sink().GetFirstResourceCallMatching( | |
269 PpapiHostMsg_VideoDecoder_RecyclePicture::ID, params, &msg)) | |
270 return false; | |
271 sink().ClearMessages(); | |
272 return UnpackMessage<PpapiHostMsg_VideoDecoder_RecyclePicture>(msg, | |
273 texture_id); | |
274 } | |
275 | |
276 bool CheckFlushMsg(ResourceMessageCallParams* params) { | |
277 return CheckMsg(params, PpapiHostMsg_VideoDecoder_Flush::ID); | |
278 } | |
279 | |
280 bool CheckResetMsg(ResourceMessageCallParams* params) { | |
281 return CheckMsg(params, PpapiHostMsg_VideoDecoder_Reset::ID); | |
282 } | |
283 | |
284 void ClearCallbacks(PP_Resource pp_decoder) { | |
285 ResourceMessageCallParams params; | |
286 MockCompletionCallback cb; | |
287 | |
288 // Reset to abort Decode and GetPicture callbacks. | |
289 CallReset(pp_decoder, &cb); | |
290 // Initialize params so we can reply to the Reset. | |
291 CheckResetMsg(¶ms); | |
292 // Run the Reset callback. | |
293 SendResetReply(params); | |
294 } | |
295 | |
296 private: | |
297 bool CheckMsg(ResourceMessageCallParams* params, int id) { | |
298 IPC::Message msg; | |
299 if (!sink().GetFirstResourceCallMatching(id, params, &msg)) | |
300 return false; | |
301 sink().ClearMessages(); | |
302 return true; | |
303 } | |
304 | |
305 const PPB_VideoDecoder_0_1* decoder_iface_; | |
306 | |
307 char decode_buffer_[kDecodeBufferSize]; | |
308 }; | |
309 | |
310 } // namespace | |
311 | |
312 TEST_F(VideoDecoderResourceTest, Initialize) { | |
313 // Initialize with 0 graphics3d_context should fail. | |
314 { | |
315 LockingResourceReleaser decoder(CreateDecoder()); | |
316 MockCompletionCallback cb; | |
317 int32_t result = decoder_iface()->Initialize( | |
318 decoder.get(), | |
319 0 /* invalid 3d graphics */, | |
320 PP_VIDEOPROFILE_H264MAIN, | |
321 kAllowSoftwareFallback, | |
322 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, | |
323 &cb)); | |
324 ASSERT_EQ(PP_ERROR_BADRESOURCE, result); | |
325 } | |
326 // Initialize with bad profile value should fail. | |
327 { | |
328 LockingResourceReleaser decoder(CreateDecoder()); | |
329 MockCompletionCallback cb; | |
330 int32_t result = decoder_iface()->Initialize( | |
331 decoder.get(), | |
332 1 /* non-zero resource */, | |
333 static_cast<PP_VideoProfile>(-1), | |
334 kAllowSoftwareFallback, | |
335 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, | |
336 &cb)); | |
337 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); | |
338 } | |
339 // Initialize with valid graphics3d_context and profile should succeed. | |
340 { | |
341 LockingResourceReleaser decoder(CreateDecoder()); | |
342 LockingResourceReleaser graphics3d(CreateGraphics3d()); | |
343 MockCompletionCallback cb; | |
344 int32_t result = decoder_iface()->Initialize( | |
345 decoder.get(), | |
346 graphics3d.get(), | |
347 PP_VIDEOPROFILE_H264MAIN, | |
348 kAllowSoftwareFallback, | |
349 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, | |
350 &cb)); | |
351 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); | |
352 ASSERT_TRUE(decoder_iface()->IsVideoDecoder(decoder.get())); | |
353 | |
354 // Another attempt while pending should fail. | |
355 result = decoder_iface()->Initialize( | |
356 decoder.get(), | |
357 graphics3d.get(), | |
358 PP_VIDEOPROFILE_H264MAIN, | |
359 kAllowSoftwareFallback, | |
360 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback, | |
361 &cb)); | |
362 ASSERT_EQ(PP_ERROR_INPROGRESS, result); | |
363 | |
364 // Check for host message and send a reply to complete initialization. | |
365 ResourceMessageCallParams params; | |
366 IPC::Message msg; | |
367 ASSERT_TRUE(sink().GetFirstResourceCallMatching( | |
368 PpapiHostMsg_VideoDecoder_Initialize::ID, ¶ms, &msg)); | |
369 sink().ClearMessages(); | |
370 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_InitializeReply()); | |
371 ASSERT_TRUE(cb.called()); | |
372 ASSERT_EQ(PP_OK, cb.result()); | |
373 } | |
374 } | |
375 | |
376 TEST_F(VideoDecoderResourceTest, Uninitialized) { | |
377 // Operations on uninitialized decoders should fail. | |
378 LockingResourceReleaser decoder(CreateDecoder()); | |
379 MockCompletionCallback uncalled_cb; | |
380 | |
381 ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb, NULL)); | |
382 ASSERT_FALSE(uncalled_cb.called()); | |
383 | |
384 ASSERT_EQ(PP_ERROR_FAILED, CallGetPicture(decoder.get(), NULL, &uncalled_cb)); | |
385 ASSERT_FALSE(uncalled_cb.called()); | |
386 | |
387 ASSERT_EQ(PP_ERROR_FAILED, CallFlush(decoder.get(), &uncalled_cb)); | |
388 ASSERT_FALSE(uncalled_cb.called()); | |
389 | |
390 ASSERT_EQ(PP_ERROR_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
391 ASSERT_FALSE(uncalled_cb.called()); | |
392 } | |
393 | |
394 TEST_F(VideoDecoderResourceTest, DecodeAndGetPicture) { | |
395 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
396 ResourceMessageCallParams params, params2; | |
397 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
398 | |
399 uint32_t shm_id; | |
400 uint32_t decode_size; | |
401 // Call Decode until we have the maximum pending, minus one. | |
402 for (uint32_t i = 0; i < kMaximumPendingDecodes - 1; i++) { | |
403 PpapiHostMsg_VideoDecoder_GetShm shm_msg(i, kDecodeBufferSize); | |
404 ASSERT_EQ(PP_OK, CallDecode(decoder.get(), &uncalled_cb, &shm_msg)); | |
405 ASSERT_FALSE(uncalled_cb.called()); | |
406 CheckDecodeMsg(¶ms, &shm_id, &decode_size); | |
407 ASSERT_EQ(i, shm_id); | |
408 ASSERT_EQ(kDecodeBufferSize, decode_size); | |
409 } | |
410 // Once we've allocated the maximum number of buffers, we must wait. | |
411 PpapiHostMsg_VideoDecoder_GetShm shm_msg(7U, kDecodeBufferSize); | |
412 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
413 CallDecode(decoder.get(), &decode_cb, &shm_msg)); | |
414 CheckDecodeMsg(¶ms, &shm_id, &decode_size); | |
415 ASSERT_EQ(7U, shm_id); | |
416 ASSERT_EQ(kDecodeBufferSize, decode_size); | |
417 | |
418 // Calling Decode when another Decode is pending should fail. | |
419 ASSERT_EQ(PP_ERROR_INPROGRESS, CallDecode(decoder.get(), &uncalled_cb, NULL)); | |
420 ASSERT_FALSE(uncalled_cb.called()); | |
421 // Free up the first decode buffer. | |
422 SendDecodeReply(params, 0U); | |
423 // The decoder should run the pending callback. | |
424 ASSERT_TRUE(decode_cb.called()); | |
425 ASSERT_EQ(PP_OK, decode_cb.result()); | |
426 decode_cb.Reset(); | |
427 | |
428 // Now try to get a picture. No picture ready message has been received yet. | |
429 PP_VideoPicture picture; | |
430 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
431 CallGetPicture(decoder.get(), &picture, &get_picture_cb)); | |
432 ASSERT_FALSE(get_picture_cb.called()); | |
433 // Calling GetPicture when another GetPicture is pending should fail. | |
434 ASSERT_EQ(PP_ERROR_INPROGRESS, | |
435 CallGetPicture(decoder.get(), &picture, &uncalled_cb)); | |
436 ASSERT_FALSE(uncalled_cb.called()); | |
437 // Send 'request textures' message to initialize textures. | |
438 SendRequestTextures(params); | |
439 // Send a picture ready message for Decode call 0. The GetPicture callback | |
440 // should complete. | |
441 SendPictureReady(params, 0U, kTextureId1); | |
442 ASSERT_TRUE(get_picture_cb.called()); | |
443 ASSERT_EQ(PP_OK, get_picture_cb.result()); | |
444 ASSERT_EQ(kDecodeId, picture.decode_id); | |
445 get_picture_cb.Reset(); | |
446 | |
447 // Send a picture ready message for Decode call 1. Since there is no pending | |
448 // GetPicture call, the picture should be queued. | |
449 SendPictureReady(params, 1U, kTextureId2); | |
450 // The next GetPicture should return synchronously. | |
451 ASSERT_EQ(PP_OK, CallGetPicture(decoder.get(), &picture, &uncalled_cb)); | |
452 ASSERT_FALSE(uncalled_cb.called()); | |
453 ASSERT_EQ(kDecodeId, picture.decode_id); | |
454 } | |
455 | |
456 TEST_F(VideoDecoderResourceTest, RecyclePicture) { | |
457 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
458 ResourceMessageCallParams params; | |
459 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
460 | |
461 // Get to a state where we have a picture to recycle. | |
462 PpapiHostMsg_VideoDecoder_GetShm shm_msg(0U, kDecodeBufferSize); | |
463 ASSERT_EQ(PP_OK, CallDecode(decoder.get(), &decode_cb, &shm_msg)); | |
464 uint32_t shm_id; | |
465 uint32_t decode_size; | |
466 CheckDecodeMsg(¶ms, &shm_id, &decode_size); | |
467 SendDecodeReply(params, 0U); | |
468 // Send 'request textures' message to initialize textures. | |
469 SendRequestTextures(params); | |
470 // Call GetPicture and send 'picture ready' message to get a picture to | |
471 // recycle. | |
472 PP_VideoPicture picture; | |
473 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
474 CallGetPicture(decoder.get(), &picture, &get_picture_cb)); | |
475 SendPictureReady(params, 0U, kTextureId1); | |
476 ASSERT_EQ(kTextureId1, picture.texture_id); | |
477 | |
478 CallRecyclePicture(decoder.get(), picture); | |
479 uint32_t texture_id; | |
480 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms, &texture_id)); | |
481 ASSERT_EQ(kTextureId1, texture_id); | |
482 | |
483 ClearCallbacks(decoder.get()); | |
484 } | |
485 | |
486 TEST_F(VideoDecoderResourceTest, Flush) { | |
487 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
488 ResourceMessageCallParams params, params2; | |
489 MockCompletionCallback flush_cb, get_picture_cb, uncalled_cb; | |
490 | |
491 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallFlush(decoder.get(), &flush_cb)); | |
492 ASSERT_FALSE(flush_cb.called()); | |
493 ASSERT_TRUE(CheckFlushMsg(¶ms)); | |
494 | |
495 ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb, NULL)); | |
496 ASSERT_FALSE(uncalled_cb.called()); | |
497 | |
498 // Plugin can call GetPicture while Flush is pending. | |
499 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
500 CallGetPicture(decoder.get(), NULL, &get_picture_cb)); | |
501 ASSERT_FALSE(get_picture_cb.called()); | |
502 | |
503 ASSERT_EQ(PP_ERROR_INPROGRESS, CallFlush(decoder.get(), &uncalled_cb)); | |
504 ASSERT_FALSE(uncalled_cb.called()); | |
505 | |
506 ASSERT_EQ(PP_ERROR_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
507 ASSERT_FALSE(uncalled_cb.called()); | |
508 | |
509 // Plugin can call RecyclePicture while Flush is pending. | |
510 PP_VideoPicture picture; | |
511 picture.texture_id = kTextureId1; | |
512 CallRecyclePicture(decoder.get(), picture); | |
513 uint32_t texture_id; | |
514 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms2, &texture_id)); | |
515 | |
516 SendFlushReply(params); | |
517 // Any pending GetPicture call is aborted. | |
518 ASSERT_TRUE(get_picture_cb.called()); | |
519 ASSERT_EQ(PP_ERROR_ABORTED, get_picture_cb.result()); | |
520 ASSERT_TRUE(flush_cb.called()); | |
521 ASSERT_EQ(PP_OK, flush_cb.result()); | |
522 } | |
523 | |
524 // TODO(bbudge) Test Reset when we can run the message loop to get aborted | |
525 // callbacks to run. | |
526 | |
527 TEST_F(VideoDecoderResourceTest, NotifyError) { | |
528 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
529 ResourceMessageCallParams params; | |
530 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
531 | |
532 // Call Decode and GetPicture to have some pending requests. | |
533 PpapiHostMsg_VideoDecoder_GetShm shm_msg(0U, kDecodeBufferSize); | |
534 ASSERT_EQ(PP_OK, CallDecode(decoder.get(), &decode_cb, &shm_msg)); | |
535 ASSERT_FALSE(decode_cb.called()); | |
536 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
537 CallGetPicture(decoder.get(), NULL, &get_picture_cb)); | |
538 ASSERT_FALSE(get_picture_cb.called()); | |
539 | |
540 // Send the decoder resource an unsolicited notify error message. We first | |
541 // need to initialize 'params' so the message is routed to the decoder. | |
542 uint32_t shm_id; | |
543 uint32_t decode_size; | |
544 CheckDecodeMsg(¶ms, &shm_id, &decode_size); | |
545 SendNotifyError(params, PP_ERROR_RESOURCE_FAILED); | |
546 | |
547 // Any pending message should be run with the reported error. | |
548 ASSERT_TRUE(get_picture_cb.called()); | |
549 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, get_picture_cb.result()); | |
550 | |
551 // All further calls return the reported error. | |
552 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, | |
553 CallDecode(decoder.get(), &uncalled_cb, NULL)); | |
554 ASSERT_FALSE(uncalled_cb.called()); | |
555 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, | |
556 CallGetPicture(decoder.get(), NULL, &uncalled_cb)); | |
557 ASSERT_FALSE(uncalled_cb.called()); | |
558 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, CallFlush(decoder.get(), &uncalled_cb)); | |
559 ASSERT_FALSE(uncalled_cb.called()); | |
560 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
561 ASSERT_FALSE(uncalled_cb.called()); | |
562 } | |
563 | |
564 } // namespace proxy | |
565 } // namespace ppapi | |
OLD | NEW |