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_resource.h" | |
18 #include "ppapi/shared_impl/proxy_lock.h" | |
19 #include "ppapi/thunk/thunk.h" | |
20 | |
21 using ppapi::proxy::ResourceMessageTestSink; | |
22 | |
23 namespace ppapi { | |
24 namespace proxy { | |
25 | |
26 namespace { | |
27 | |
28 const PP_Bool kAllowSoftwareFallback = PP_TRUE; | |
29 const PP_Resource kGraphics3D = 7; | |
30 const uint32_t kDecodeBufferSize = 16; | |
31 const uint32_t kDecodeId = 5; | |
32 const uint32_t kTextureId1 = 1; | |
33 const uint32_t kTextureId2 = 2; | |
34 const uint32_t kNumRequestedTextures = 2; | |
35 | |
36 class MockCompletionCallback { | |
37 public: | |
38 MockCompletionCallback() : called_(false) {} | |
39 | |
40 bool called() { return called_; } | |
41 int32_t result() { return result_; } | |
42 | |
43 void Reset() { called_ = false; } | |
44 | |
45 static void Callback(void* user_data, int32_t result) { | |
46 MockCompletionCallback* that = | |
47 reinterpret_cast<MockCompletionCallback*>(user_data); | |
48 that->called_ = true; | |
49 that->result_ = result; | |
50 } | |
51 | |
52 private: | |
53 bool called_; | |
54 int32_t result_; | |
55 }; | |
56 | |
57 class VideoDecoderResourceTest : public PluginProxyTest { | |
58 public: | |
59 const PPB_VideoDecoder_0_1* decoder_iface; | |
60 const PPB_Graphics3D_1_0* graphics3d_iface; | |
61 | |
62 VideoDecoderResourceTest() | |
63 : decoder_iface(thunk::GetPPB_VideoDecoder_0_1_Thunk()), | |
64 graphics3d_iface(thunk::GetPPB_Graphics3D_1_0_Thunk()) {} | |
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 = | |
117 decoder_iface->Initialize(decoder, | |
118 graphics3d.get(), | |
119 PP_VIDEOPROFILE_H264MAIN, | |
120 PP_TRUE /* allow_software_fallback */, | |
121 PP_MakeOptionalCompletionCallback( | |
122 &MockCompletionCallback::Callback, &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, MockCompletionCallback* cb) { | |
144 char decode_buffer[kDecodeBufferSize]; | |
145 memset(decode_buffer, 0x55, kDecodeBufferSize); | |
146 int32_t result = | |
147 decoder_iface->Decode(pp_decoder, | |
148 kDecodeId, | |
149 kDecodeBufferSize, | |
150 decode_buffer, | |
151 PP_MakeOptionalCompletionCallback( | |
152 &MockCompletionCallback::Callback, cb)); | |
piman
2014/05/15 04:02:53
This is an illegal call.
decode_buffer is on the s
bbudge
2014/05/15 16:31:57
Agreed, this is illegal and only works because we
dmichael (off chromium)
2014/05/15 21:18:22
It is a bit confusing, though... it's not an out-
bbudge
2014/05/15 22:27:44
I'd like to keep the API simple. I think FileIO Re
| |
153 return result; | |
154 } | |
155 | |
156 int32_t CallGetPicture(PP_Resource pp_decoder, | |
157 PP_VideoPicture* picture, | |
158 MockCompletionCallback* cb) { | |
159 int32_t result = | |
160 decoder_iface->GetPicture(pp_decoder, | |
161 picture, | |
162 PP_MakeOptionalCompletionCallback( | |
163 &MockCompletionCallback::Callback, cb)); | |
164 return result; | |
165 } | |
166 | |
167 void CallRecyclePicture(PP_Resource pp_decoder, | |
168 const PP_VideoPicture& picture) { | |
169 decoder_iface->RecyclePicture(pp_decoder, &picture); | |
170 } | |
171 | |
172 int32_t CallFlush(PP_Resource pp_decoder, MockCompletionCallback* cb) { | |
173 int32_t result = | |
174 decoder_iface->Flush(pp_decoder, | |
175 PP_MakeOptionalCompletionCallback( | |
176 &MockCompletionCallback::Callback, cb)); | |
177 return result; | |
178 } | |
179 | |
180 int32_t CallReset(PP_Resource pp_decoder, MockCompletionCallback* cb) { | |
181 int32_t result = | |
182 decoder_iface->Reset(pp_decoder, | |
183 PP_MakeOptionalCompletionCallback( | |
184 &MockCompletionCallback::Callback, cb)); | |
185 return result; | |
186 } | |
187 | |
188 void SendGetShmReply(const ResourceMessageCallParams& params, uint32_t size) { | |
189 SendReplyWithHandle(params, | |
190 PP_OK, | |
191 PpapiPluginMsg_VideoDecoder_GetShmReply(size), | |
192 CreateSharedMemory(size)); | |
193 } | |
194 | |
195 void SendDecodeReply(const ResourceMessageCallParams& params, | |
196 uint32_t shm_id) { | |
197 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_DecodeReply(shm_id)); | |
198 } | |
199 | |
200 void SendPictureReady(const ResourceMessageCallParams& params, | |
201 uint32_t shm_id, | |
202 uint32_t texture_id) { | |
203 SendReply(params, | |
204 PP_OK, | |
205 PpapiPluginMsg_VideoDecoder_PictureReady(shm_id, texture_id)); | |
206 } | |
207 | |
208 void SendFlushReply(const ResourceMessageCallParams& params) { | |
209 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_FlushReply()); | |
210 } | |
211 | |
212 void SendResetReply(const ResourceMessageCallParams& params) { | |
213 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_ResetReply()); | |
214 } | |
215 | |
216 void SendRequestTextures(const ResourceMessageCallParams& params) { | |
217 SendReply(params, | |
218 PP_OK, | |
219 PpapiPluginMsg_VideoDecoder_RequestTextures( | |
220 kNumRequestedTextures, PP_MakeSize(320, 240), GL_TEXTURE_2D)); | |
221 } | |
222 | |
223 void SendNotifyError(const ResourceMessageCallParams& params, int32_t error) { | |
224 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_NotifyError(error)); | |
225 } | |
226 | |
227 bool CheckGetShmMsg(ResourceMessageCallParams* params, uint32_t* size) { | |
228 IPC::Message msg; | |
229 if (!sink().GetFirstResourceCallMatching( | |
230 PpapiHostMsg_VideoDecoder_GetShm::ID, params, &msg)) | |
231 return false; | |
232 sink().ClearMessages(); | |
233 return UnpackMessage<PpapiHostMsg_VideoDecoder_GetShm>(msg, size); | |
234 } | |
235 | |
236 bool CheckDecodeMsg(ResourceMessageCallParams* params, | |
237 uint32_t* shm_id, | |
238 uint32_t* decode_id, | |
239 uint32_t* size) { | |
240 IPC::Message msg; | |
241 if (!sink().GetFirstResourceCallMatching( | |
242 PpapiHostMsg_VideoDecoder_Decode::ID, params, &msg)) | |
243 return false; | |
244 sink().ClearMessages(); | |
245 return UnpackMessage<PpapiHostMsg_VideoDecoder_Decode>( | |
246 msg, shm_id, decode_id, size); | |
247 } | |
248 | |
249 bool CheckRecyclePictureMsg(ResourceMessageCallParams* params, | |
250 uint32_t* texture_id) { | |
251 IPC::Message msg; | |
252 if (!sink().GetFirstResourceCallMatching( | |
253 PpapiHostMsg_VideoDecoder_RecyclePicture::ID, params, &msg)) | |
254 return false; | |
255 sink().ClearMessages(); | |
256 return UnpackMessage<PpapiHostMsg_VideoDecoder_RecyclePicture>(msg, | |
257 texture_id); | |
258 } | |
259 | |
260 bool CheckFlushMsg(ResourceMessageCallParams* params) { | |
261 return CheckMsg(params, PpapiHostMsg_VideoDecoder_Flush::ID); | |
262 } | |
263 | |
264 bool CheckResetMsg(ResourceMessageCallParams* params) { | |
265 return CheckMsg(params, PpapiHostMsg_VideoDecoder_Reset::ID); | |
266 } | |
267 | |
268 void ClearCallbacks(PP_Resource pp_decoder) { | |
269 ResourceMessageCallParams params; | |
270 MockCompletionCallback cb; | |
271 | |
272 // Reset to abort Decode and GetPicture callbacks. | |
273 CallReset(pp_decoder, &cb); | |
274 // Initialize params so we can reply to the Reset. | |
275 CheckResetMsg(¶ms); | |
276 // Run the Reset callback. | |
277 SendResetReply(params); | |
278 } | |
279 | |
280 private: | |
281 bool CheckMsg(ResourceMessageCallParams* params, int id) { | |
282 IPC::Message msg; | |
283 if (!sink().GetFirstResourceCallMatching(id, params, &msg)) | |
284 return false; | |
285 sink().ClearMessages(); | |
286 return true; | |
287 } | |
288 }; | |
289 | |
290 } // namespace | |
291 | |
292 TEST_F(VideoDecoderResourceTest, Initialize) { | |
293 // Initialize with 0 graphics3d_context should fail. | |
294 { | |
295 LockingResourceReleaser decoder(CreateDecoder()); | |
296 MockCompletionCallback cb; | |
297 int32_t result = | |
298 decoder_iface->Initialize(decoder.get(), | |
299 0 /* invalid 3d graphics */, | |
300 PP_VIDEOPROFILE_H264MAIN, | |
301 kAllowSoftwareFallback, | |
302 PP_MakeOptionalCompletionCallback( | |
303 &MockCompletionCallback::Callback, &cb)); | |
304 ASSERT_EQ(PP_ERROR_BADRESOURCE, result); | |
305 } | |
306 // Initialize with bad profile value should fail. | |
307 { | |
308 LockingResourceReleaser decoder(CreateDecoder()); | |
309 MockCompletionCallback cb; | |
310 int32_t result = | |
311 decoder_iface->Initialize(decoder.get(), | |
312 1 /* non-zero resource */, | |
313 static_cast<PP_VideoProfile>(-1), | |
314 kAllowSoftwareFallback, | |
315 PP_MakeOptionalCompletionCallback( | |
316 &MockCompletionCallback::Callback, &cb)); | |
317 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); | |
318 } | |
319 // Initialize with valid graphics3d_context and profile should succeed. | |
320 { | |
321 LockingResourceReleaser decoder(CreateDecoder()); | |
322 LockingResourceReleaser graphics3d(CreateGraphics3d()); | |
323 MockCompletionCallback cb; | |
324 int32_t result = | |
325 decoder_iface->Initialize(decoder.get(), | |
326 graphics3d.get(), | |
327 PP_VIDEOPROFILE_H264MAIN, | |
328 kAllowSoftwareFallback, | |
329 PP_MakeOptionalCompletionCallback( | |
330 &MockCompletionCallback::Callback, &cb)); | |
331 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); | |
332 ASSERT_TRUE(decoder_iface->IsVideoDecoder(decoder.get())); | |
333 | |
334 // Another attempt while pending should fail. | |
335 result = | |
336 decoder_iface->Initialize(decoder.get(), | |
337 graphics3d.get(), | |
338 PP_VIDEOPROFILE_H264MAIN, | |
339 kAllowSoftwareFallback, | |
340 PP_MakeOptionalCompletionCallback( | |
341 &MockCompletionCallback::Callback, &cb)); | |
342 ASSERT_EQ(PP_ERROR_INPROGRESS, result); | |
343 | |
344 // Check for host message and send a reply to complete initialization. | |
345 ResourceMessageCallParams params; | |
346 IPC::Message msg; | |
347 ASSERT_TRUE(sink().GetFirstResourceCallMatching( | |
348 PpapiHostMsg_VideoDecoder_Initialize::ID, ¶ms, &msg)); | |
349 sink().ClearMessages(); | |
350 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_InitializeReply()); | |
351 ASSERT_TRUE(cb.called()); | |
352 ASSERT_EQ(PP_OK, cb.result()); | |
353 } | |
354 } | |
355 | |
356 TEST_F(VideoDecoderResourceTest, Uninitialized) { | |
357 // Operations on uninitialized decoders should fail. | |
358 LockingResourceReleaser decoder(CreateDecoder()); | |
359 MockCompletionCallback uncalled_cb; | |
360 | |
361 ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb)); | |
362 ASSERT_FALSE(uncalled_cb.called()); | |
363 | |
364 ASSERT_EQ(PP_ERROR_FAILED, CallGetPicture(decoder.get(), NULL, &uncalled_cb)); | |
365 ASSERT_FALSE(uncalled_cb.called()); | |
366 | |
367 ASSERT_EQ(PP_ERROR_FAILED, CallFlush(decoder.get(), &uncalled_cb)); | |
368 ASSERT_FALSE(uncalled_cb.called()); | |
369 | |
370 ASSERT_EQ(PP_ERROR_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
371 ASSERT_FALSE(uncalled_cb.called()); | |
372 } | |
373 | |
374 TEST_F(VideoDecoderResourceTest, DecodeAndGetPicture) { | |
375 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
376 ResourceMessageCallParams params, params2; // TODO rename? | |
377 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
378 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallDecode(decoder.get(), &decode_cb)); | |
379 ASSERT_FALSE(decode_cb.called()); | |
380 | |
381 // Calling Decode when another Decode is pending should fail. | |
382 ASSERT_EQ(PP_ERROR_INPROGRESS, CallDecode(decoder.get(), &uncalled_cb)); | |
383 ASSERT_FALSE(uncalled_cb.called()); | |
384 | |
385 // Check for host message to create shm and send a reply with handle. | |
386 uint32_t shm_buffer_size; | |
387 ASSERT_TRUE(CheckGetShmMsg(¶ms, &shm_buffer_size)); | |
388 ASSERT_GE(shm_buffer_size, kDecodeBufferSize); | |
389 SendGetShmReply(params, shm_buffer_size); | |
390 // The decoder should copy the user data and send a Decode message. | |
391 uint32_t shm_id; | |
392 uint32_t decode_id; | |
393 uint32_t decode_size; | |
394 ASSERT_TRUE(CheckDecodeMsg(¶ms, &shm_id, &decode_id, &decode_size)); | |
395 // Buffer id is 0. | |
396 ASSERT_EQ(0U, shm_id); | |
397 ASSERT_EQ(kDecodeId, decode_id); | |
398 ASSERT_EQ(kDecodeBufferSize, decode_size); | |
399 // The decoder should run the callback. | |
400 ASSERT_TRUE(decode_cb.called()); | |
401 ASSERT_EQ(PP_OK, decode_cb.result()); | |
402 decode_cb.Reset(); | |
403 | |
404 // The decoder only has 1 shm buffer and it is still in use. The next Decode | |
405 // call should also cause a shm buffer to be created. | |
406 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallDecode(decoder.get(), &decode_cb)); | |
407 ASSERT_FALSE(decode_cb.called()); | |
408 // Check for another host message to create shm and send a reply with handle. | |
409 ASSERT_TRUE(CheckGetShmMsg(¶ms2, &shm_buffer_size)); | |
410 SendGetShmReply(params2, shm_buffer_size); | |
411 | |
412 // The decoder should copy the user data and send the host message to Decode. | |
413 ASSERT_TRUE(CheckDecodeMsg(¶ms2, &shm_id, &decode_id, &decode_size)); | |
414 // Buffer id should be 1. | |
415 ASSERT_EQ(1U, shm_id); | |
416 ASSERT_EQ(kDecodeBufferSize, decode_size); | |
417 // The decoder should run the plugin's callback. | |
418 ASSERT_TRUE(decode_cb.called()); | |
419 ASSERT_EQ(PP_OK, decode_cb.result()); | |
420 decode_cb.Reset(); | |
421 | |
422 // Now send a reply for both in-flight decodes. This should free up shm | |
423 // buffers 0 and 1, and set the picture ids for them. | |
424 SendDecodeReply(params, 0U); | |
425 SendDecodeReply(params2, 1U); | |
426 | |
427 // Calling Decode when a shm buffer is available should complete | |
428 // synchronously. | |
429 ASSERT_EQ(PP_OK, CallDecode(decoder.get(), &uncalled_cb)); | |
430 ASSERT_FALSE(uncalled_cb.called()); | |
431 | |
432 // Now try to get a picture. No picture ready message has been received yet. | |
433 PP_VideoPicture picture; | |
434 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
435 CallGetPicture(decoder.get(), &picture, &get_picture_cb)); | |
436 ASSERT_FALSE(get_picture_cb.called()); | |
437 // Calling GetPicture when another GetPicture is pending should fail. | |
438 ASSERT_EQ(PP_ERROR_INPROGRESS, | |
439 CallGetPicture(decoder.get(), &picture, &uncalled_cb)); | |
440 ASSERT_FALSE(uncalled_cb.called()); | |
441 // Send 'request textures' message to initialize textures. | |
442 SendRequestTextures(params); | |
443 // Send a picture ready message for shm 0. The callback should complete. | |
444 SendPictureReady(params, kDecodeId, kTextureId1); | |
445 ASSERT_TRUE(get_picture_cb.called()); | |
446 ASSERT_EQ(PP_OK, get_picture_cb.result()); | |
447 ASSERT_EQ(kDecodeId, picture.decode_id); | |
448 get_picture_cb.Reset(); | |
449 | |
450 // Send another picture ready message. Since there is no pending GetPicture | |
451 // call, the picture should be queued. | |
452 SendPictureReady(params, kDecodeId + 1, kTextureId2); | |
453 // The next GetPicture should return synchronously. | |
454 ASSERT_EQ(PP_OK, CallGetPicture(decoder.get(), &picture, &uncalled_cb)); | |
455 ASSERT_FALSE(uncalled_cb.called()); | |
456 ASSERT_EQ(kDecodeId + 1, picture.decode_id); | |
457 } | |
458 | |
459 TEST_F(VideoDecoderResourceTest, RecyclePicture) { | |
460 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
461 ResourceMessageCallParams params; | |
462 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
463 | |
464 // Call Decode, which sends a message that we can check, which will initialize | |
465 // 'params' so we can send a 'picture ready' message. | |
466 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallDecode(decoder.get(), &decode_cb)); | |
467 ASSERT_FALSE(decode_cb.called()); | |
468 uint32_t shm_buffer_size; | |
469 CheckGetShmMsg(¶ms, &shm_buffer_size); | |
470 // Send 'request textures' message to initialize textures. | |
471 SendRequestTextures(params); | |
472 // Call GetPicture and send 'picture ready' message to get a picture to | |
473 // recycle. | |
474 PP_VideoPicture picture; | |
475 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
476 CallGetPicture(decoder.get(), &picture, &get_picture_cb)); | |
477 SendPictureReady(params, 0U, kTextureId1); | |
478 ASSERT_EQ(kTextureId1, picture.texture_id); | |
479 | |
480 CallRecyclePicture(decoder.get(), picture); | |
481 uint32_t texture_id; | |
482 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms, &texture_id)); | |
483 ASSERT_EQ(kTextureId1, texture_id); | |
484 | |
485 ClearCallbacks(decoder.get()); | |
486 } | |
487 | |
488 TEST_F(VideoDecoderResourceTest, Flush) { | |
489 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
490 ResourceMessageCallParams params, params2; | |
491 MockCompletionCallback flush_cb, get_picture_cb, uncalled_cb; | |
492 | |
493 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallFlush(decoder.get(), &flush_cb)); | |
494 ASSERT_FALSE(flush_cb.called()); | |
495 ASSERT_TRUE(CheckFlushMsg(¶ms)); | |
496 | |
497 ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb)); | |
498 ASSERT_FALSE(uncalled_cb.called()); | |
499 | |
500 // Plugin can call GetPicture while Flush is pending. | |
501 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
502 CallGetPicture(decoder.get(), NULL, &get_picture_cb)); | |
503 ASSERT_FALSE(get_picture_cb.called()); | |
504 | |
505 ASSERT_EQ(PP_ERROR_INPROGRESS, CallFlush(decoder.get(), &uncalled_cb)); | |
506 ASSERT_FALSE(uncalled_cb.called()); | |
507 | |
508 ASSERT_EQ(PP_ERROR_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
509 ASSERT_FALSE(uncalled_cb.called()); | |
510 | |
511 // Plugin can call RecyclePicture while Flush is pending. | |
512 PP_VideoPicture picture; | |
513 picture.texture_id = kTextureId1; | |
514 CallRecyclePicture(decoder.get(), picture); | |
515 uint32_t texture_id; | |
516 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms2, &texture_id)); | |
517 | |
518 SendFlushReply(params); | |
519 // Any pending GetPicture call is aborted. | |
520 ASSERT_TRUE(get_picture_cb.called()); | |
521 ASSERT_EQ(PP_ERROR_ABORTED, get_picture_cb.result()); | |
522 ASSERT_TRUE(flush_cb.called()); | |
523 ASSERT_EQ(PP_OK, flush_cb.result()); | |
524 } | |
525 | |
526 TEST_F(VideoDecoderResourceTest, Reset) { | |
527 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
528 ResourceMessageCallParams params; | |
529 MockCompletionCallback reset_cb, decode_cb, get_picture_cb, uncalled_cb; | |
530 | |
531 // Call Decode and GetPicture to have some pending requests. | |
532 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallDecode(decoder.get(), &decode_cb)); | |
533 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
534 CallGetPicture(decoder.get(), NULL, &get_picture_cb)); | |
535 | |
536 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallReset(decoder.get(), &reset_cb)); | |
537 ASSERT_FALSE(reset_cb.called()); | |
538 ASSERT_TRUE(CheckResetMsg(¶ms)); | |
539 // Pending calls should be aborted. | |
540 ASSERT_TRUE(decode_cb.called()); | |
541 ASSERT_EQ(PP_ERROR_ABORTED, decode_cb.result()); | |
542 ASSERT_TRUE(get_picture_cb.called()); | |
543 ASSERT_EQ(PP_ERROR_ABORTED, get_picture_cb.result()); | |
544 | |
545 // No calls can be made while Reset is pending. | |
546 ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb)); | |
547 ASSERT_FALSE(uncalled_cb.called()); | |
548 ASSERT_EQ(PP_ERROR_FAILED, CallGetPicture(decoder.get(), NULL, &uncalled_cb)); | |
549 ASSERT_FALSE(uncalled_cb.called()); | |
550 ASSERT_EQ(PP_ERROR_FAILED, CallFlush(decoder.get(), &uncalled_cb)); | |
551 ASSERT_FALSE(uncalled_cb.called()); | |
552 ASSERT_EQ(PP_ERROR_INPROGRESS, CallReset(decoder.get(), &uncalled_cb)); | |
553 ASSERT_FALSE(uncalled_cb.called()); | |
554 | |
555 SendResetReply(params); | |
556 ASSERT_TRUE(reset_cb.called()); | |
557 ASSERT_EQ(PP_OK, reset_cb.result()); | |
558 } | |
559 | |
560 TEST_F(VideoDecoderResourceTest, NotifyError) { | |
561 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
562 ResourceMessageCallParams params; | |
563 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
564 | |
565 // Call Decode and GetPicture to have some pending requests. | |
566 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallDecode(decoder.get(), &decode_cb)); | |
567 ASSERT_FALSE(decode_cb.called()); | |
568 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
569 CallGetPicture(decoder.get(), NULL, &get_picture_cb)); | |
570 ASSERT_FALSE(get_picture_cb.called()); | |
571 | |
572 // Send the decoder resource an unsolicited notify error message. We first | |
573 // need to initialize 'params' so the message is routed to the decoder. | |
574 uint32_t shm_buffer_size; | |
575 CheckGetShmMsg(¶ms, &shm_buffer_size); | |
576 SendNotifyError(params, PP_ERROR_PLATFORM_FAILED); | |
577 | |
578 // Both pending messages should be run with the reported error. | |
579 ASSERT_TRUE(decode_cb.called()); | |
580 ASSERT_EQ(PP_ERROR_PLATFORM_FAILED, decode_cb.result()); | |
581 ASSERT_TRUE(get_picture_cb.called()); | |
582 ASSERT_EQ(PP_ERROR_PLATFORM_FAILED, get_picture_cb.result()); | |
583 | |
584 // All further calls return the reported error. | |
585 ASSERT_EQ(PP_ERROR_PLATFORM_FAILED, CallDecode(decoder.get(), &uncalled_cb)); | |
586 ASSERT_FALSE(uncalled_cb.called()); | |
587 ASSERT_EQ(PP_ERROR_PLATFORM_FAILED, | |
588 CallGetPicture(decoder.get(), NULL, &uncalled_cb)); | |
589 ASSERT_FALSE(uncalled_cb.called()); | |
590 ASSERT_EQ(PP_ERROR_PLATFORM_FAILED, CallFlush(decoder.get(), &uncalled_cb)); | |
591 ASSERT_FALSE(uncalled_cb.called()); | |
592 ASSERT_EQ(PP_ERROR_PLATFORM_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
593 ASSERT_FALSE(uncalled_cb.called()); | |
594 } | |
595 | |
596 } // namespace proxy | |
597 } // namespace ppapi | |
OLD | NEW |