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.
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"
22 using ppapi::proxy::ResourceMessageTestSink
;
29 const PP_Resource kGraphics3D
= 7;
30 const uint32_t kShmSize
= 256;
31 const size_t kDecodeBufferSize
= 16;
32 const uint32_t kDecodeId
= 5;
33 const uint32_t kTextureId1
= 1;
34 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
35 const uint32_t kTextureId2
= 2;
37 const uint32_t kNumRequestedTextures
= 2;
39 class MockCompletionCallback
{
41 MockCompletionCallback() : called_(false) {}
43 bool called() { return called_
; }
44 int32_t result() { return result_
; }
46 void Reset() { called_
= false; }
48 static void Callback(void* user_data
, int32_t result
) {
49 MockCompletionCallback
* that
=
50 reinterpret_cast<MockCompletionCallback
*>(user_data
);
52 that
->result_
= result
;
60 class VideoDecoderResourceTest
: public PluginProxyTest
{
62 VideoDecoderResourceTest()
63 : decoder_iface_(thunk::GetPPB_VideoDecoder_1_0_Thunk()) {}
65 const PPB_VideoDecoder_1_0
* decoder_iface() const { return decoder_iface_
; }
67 void SendReply(const ResourceMessageCallParams
& params
,
69 const IPC::Message
& nested_message
) {
70 ResourceMessageReplyParams
reply_params(params
.pp_resource(),
72 reply_params
.set_result(result
);
73 PluginMessageFilter::DispatchResourceReplyForTest(reply_params
,
77 void SendReplyWithHandle(const ResourceMessageCallParams
& params
,
79 const IPC::Message
& nested_message
,
80 const SerializedHandle
& handle
) {
81 ResourceMessageReplyParams
reply_params(params
.pp_resource(),
83 reply_params
.set_result(result
);
84 reply_params
.AppendHandle(handle
);
85 PluginMessageFilter::DispatchResourceReplyForTest(reply_params
,
89 PP_Resource
CreateDecoder() {
90 PP_Resource result
= decoder_iface()->Create(pp_instance());
93 ppapi::Resource
* resource
=
94 GetGlobals()->GetResourceTracker()->GetResource(result
);
95 proxy::VideoDecoderResource
* decoder
=
96 static_cast<proxy::VideoDecoderResource
*>(resource
);
97 decoder
->SetForTest();
103 PP_Resource
CreateGraphics3d() {
106 HostResource host_resource
;
107 host_resource
.SetHostResource(pp_instance(), kGraphics3D
);
108 scoped_refptr
<ppapi::proxy::Graphics3D
> graphics_3d(
109 new ppapi::proxy::Graphics3D(host_resource
));
110 return graphics_3d
->GetReference();
113 PP_Resource
CreateAndInitializeDecoder() {
114 PP_Resource decoder
= CreateDecoder();
115 LockingResourceReleaser
graphics3d(CreateGraphics3d());
116 MockCompletionCallback cb
;
117 int32_t result
= decoder_iface()->Initialize(
120 PP_VIDEOPROFILE_H264MAIN
,
121 PP_HARDWAREACCELERATION_WITHFALLBACK
,
122 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
124 if (result
!= PP_OK_COMPLETIONPENDING
)
126 ResourceMessageCallParams params
;
128 if (!sink().GetFirstResourceCallMatching(
129 PpapiHostMsg_VideoDecoder_Initialize::ID
, ¶ms
, &msg
))
131 sink().ClearMessages();
132 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_InitializeReply());
136 int32_t CallDecode(PP_Resource pp_decoder
,
137 MockCompletionCallback
* cb
,
138 const PpapiHostMsg_VideoDecoder_GetShm
* expected_shm_msg
) {
139 // Set up a handler in case the resource sends a sync message to create
141 PpapiPluginMsg_VideoDecoder_GetShmReply
shm_msg_reply(kShmSize
);
142 ResourceSyncCallHandler
shm_msg_handler(
143 &sink(), PpapiHostMsg_VideoDecoder_GetShm::ID
, PP_OK
, shm_msg_reply
);
144 sink().AddFilter(&shm_msg_handler
);
146 base::SharedMemory shm
;
147 if (expected_shm_msg
) {
148 shm
.CreateAnonymous(kShmSize
);
149 base::SharedMemoryHandle shm_handle
;
150 shm
.ShareToProcess(base::GetCurrentProcessHandle(), &shm_handle
);
151 SerializedHandle
serialized_handle(shm_handle
, kShmSize
);
152 shm_msg_handler
.set_serialized_handle(&serialized_handle
);
155 memset(decode_buffer_
, 0x55, kDecodeBufferSize
);
157 decoder_iface()->Decode(pp_decoder
,
161 PP_MakeOptionalCompletionCallback(
162 &MockCompletionCallback::Callback
, cb
));
164 if (expected_shm_msg
) {
165 uint32_t shm_id
, shm_size
, expected_shm_id
, expected_shm_size
;
166 UnpackMessage
<PpapiHostMsg_VideoDecoder_GetShm
>(
167 *expected_shm_msg
, &expected_shm_id
, &expected_shm_size
);
168 if (shm_msg_handler
.last_handled_msg().type() == 0 ||
169 !UnpackMessage
<PpapiHostMsg_VideoDecoder_GetShm
>(
170 shm_msg_handler
.last_handled_msg(), &shm_id
, &shm_size
) ||
171 shm_id
!= expected_shm_id
||
172 shm_size
!= expected_shm_size
) {
173 // Signal that the expected shm message wasn't sent by failing.
174 result
= PP_ERROR_FAILED
;
178 sink().RemoveFilter(&shm_msg_handler
);
182 int32_t CallGetPicture(PP_Resource pp_decoder
,
183 PP_VideoPicture
* picture
,
184 MockCompletionCallback
* cb
) {
186 decoder_iface()->GetPicture(pp_decoder
,
188 PP_MakeOptionalCompletionCallback(
189 &MockCompletionCallback::Callback
, cb
));
193 void CallRecyclePicture(PP_Resource pp_decoder
,
194 const PP_VideoPicture
& picture
) {
195 decoder_iface()->RecyclePicture(pp_decoder
, &picture
);
198 int32_t CallFlush(PP_Resource pp_decoder
, MockCompletionCallback
* cb
) {
200 decoder_iface()->Flush(pp_decoder
,
201 PP_MakeOptionalCompletionCallback(
202 &MockCompletionCallback::Callback
, cb
));
206 int32_t CallReset(PP_Resource pp_decoder
, MockCompletionCallback
* cb
) {
208 decoder_iface()->Reset(pp_decoder
,
209 PP_MakeOptionalCompletionCallback(
210 &MockCompletionCallback::Callback
, cb
));
214 void SendDecodeReply(const ResourceMessageCallParams
& params
,
216 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_DecodeReply(shm_id
));
219 void SendPictureReady(const ResourceMessageCallParams
& params
,
220 uint32_t decode_count
,
221 uint32_t texture_id
) {
222 PP_Rect visible_rect
= PP_MakeRectFromXYWH(0, 0, 640, 480);
223 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_PictureReady(
224 decode_count
, texture_id
, visible_rect
));
227 void SendFlushReply(const ResourceMessageCallParams
& params
) {
228 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_FlushReply());
231 void SendResetReply(const ResourceMessageCallParams
& params
) {
232 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_ResetReply());
235 void SendRequestTextures(const ResourceMessageCallParams
& params
) {
238 PpapiPluginMsg_VideoDecoder_RequestTextures(
239 kNumRequestedTextures
,
240 PP_MakeSize(320, 240),
242 std::vector
<gpu::Mailbox
>()));
245 void SendNotifyError(const ResourceMessageCallParams
& params
, int32_t error
) {
246 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_NotifyError(error
));
249 bool CheckDecodeMsg(ResourceMessageCallParams
* params
,
252 int32_t* decode_id
) {
254 if (!sink().GetFirstResourceCallMatching(
255 PpapiHostMsg_VideoDecoder_Decode::ID
, params
, &msg
))
257 sink().ClearMessages();
258 return UnpackMessage
<PpapiHostMsg_VideoDecoder_Decode
>(
259 msg
, shm_id
, size
, decode_id
);
262 bool CheckRecyclePictureMsg(ResourceMessageCallParams
* params
,
263 uint32_t* texture_id
) {
265 if (!sink().GetFirstResourceCallMatching(
266 PpapiHostMsg_VideoDecoder_RecyclePicture::ID
, params
, &msg
))
268 sink().ClearMessages();
269 return UnpackMessage
<PpapiHostMsg_VideoDecoder_RecyclePicture
>(msg
,
273 bool CheckFlushMsg(ResourceMessageCallParams
* params
) {
274 return CheckMsg(params
, PpapiHostMsg_VideoDecoder_Flush::ID
);
277 bool CheckResetMsg(ResourceMessageCallParams
* params
) {
278 return CheckMsg(params
, PpapiHostMsg_VideoDecoder_Reset::ID
);
281 void ClearCallbacks(PP_Resource pp_decoder
) {
282 ResourceMessageCallParams params
;
283 MockCompletionCallback cb
;
285 // Reset to abort Decode and GetPicture callbacks.
286 CallReset(pp_decoder
, &cb
);
287 // Initialize params so we can reply to the Reset.
288 CheckResetMsg(¶ms
);
289 // Run the Reset callback.
290 SendResetReply(params
);
294 bool CheckMsg(ResourceMessageCallParams
* params
, int id
) {
296 if (!sink().GetFirstResourceCallMatching(id
, params
, &msg
))
298 sink().ClearMessages();
302 const PPB_VideoDecoder_1_0
* decoder_iface_
;
304 char decode_buffer_
[kDecodeBufferSize
];
309 TEST_F(VideoDecoderResourceTest
, Initialize
) {
310 // Initialize with 0 graphics3d_context should fail.
312 LockingResourceReleaser
decoder(CreateDecoder());
313 MockCompletionCallback cb
;
314 int32_t result
= decoder_iface()->Initialize(
316 0 /* invalid 3d graphics */,
317 PP_VIDEOPROFILE_H264MAIN
,
318 PP_HARDWAREACCELERATION_WITHFALLBACK
,
319 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
321 ASSERT_EQ(PP_ERROR_BADRESOURCE
, result
);
323 // Initialize with bad profile value should fail.
325 LockingResourceReleaser
decoder(CreateDecoder());
326 MockCompletionCallback cb
;
327 int32_t result
= decoder_iface()->Initialize(
329 1 /* non-zero resource */,
330 static_cast<PP_VideoProfile
>(-1),
331 PP_HARDWAREACCELERATION_WITHFALLBACK
,
332 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
334 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
336 // Initialize with valid graphics3d_context and profile should succeed.
338 LockingResourceReleaser
decoder(CreateDecoder());
339 LockingResourceReleaser
graphics3d(CreateGraphics3d());
340 MockCompletionCallback cb
;
341 int32_t result
= decoder_iface()->Initialize(
344 PP_VIDEOPROFILE_H264MAIN
,
345 PP_HARDWAREACCELERATION_WITHFALLBACK
,
346 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
348 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
349 ASSERT_TRUE(decoder_iface()->IsVideoDecoder(decoder
.get()));
351 // Another attempt while pending should fail.
352 result
= decoder_iface()->Initialize(
355 PP_VIDEOPROFILE_H264MAIN
,
356 PP_HARDWAREACCELERATION_WITHFALLBACK
,
357 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
359 ASSERT_EQ(PP_ERROR_INPROGRESS
, result
);
361 // Check for host message and send a reply to complete initialization.
362 ResourceMessageCallParams params
;
364 ASSERT_TRUE(sink().GetFirstResourceCallMatching(
365 PpapiHostMsg_VideoDecoder_Initialize::ID
, ¶ms
, &msg
));
366 sink().ClearMessages();
367 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_InitializeReply());
368 ASSERT_TRUE(cb
.called());
369 ASSERT_EQ(PP_OK
, cb
.result());
373 TEST_F(VideoDecoderResourceTest
, Uninitialized
) {
374 // Operations on uninitialized decoders should fail.
375 LockingResourceReleaser
decoder(CreateDecoder());
376 MockCompletionCallback uncalled_cb
;
378 ASSERT_EQ(PP_ERROR_FAILED
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
379 ASSERT_FALSE(uncalled_cb
.called());
381 ASSERT_EQ(PP_ERROR_FAILED
, CallGetPicture(decoder
.get(), NULL
, &uncalled_cb
));
382 ASSERT_FALSE(uncalled_cb
.called());
384 ASSERT_EQ(PP_ERROR_FAILED
, CallFlush(decoder
.get(), &uncalled_cb
));
385 ASSERT_FALSE(uncalled_cb
.called());
387 ASSERT_EQ(PP_ERROR_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
388 ASSERT_FALSE(uncalled_cb
.called());
391 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
392 // message for GetShm isn't received, causing Decode to fail.
393 // http://crbug.com/379260
394 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
395 TEST_F(VideoDecoderResourceTest
, DecodeAndGetPicture
) {
396 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
397 ResourceMessageCallParams params
, params2
;
398 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
401 uint32_t decode_size
;
403 // Call Decode until we have the maximum pending, minus one.
404 for (uint32_t i
= 0; i
< kMaximumPendingDecodes
- 1; i
++) {
405 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(i
, kDecodeBufferSize
);
406 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &uncalled_cb
, &shm_msg
));
407 ASSERT_FALSE(uncalled_cb
.called());
408 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
409 ASSERT_EQ(i
, shm_id
);
410 ASSERT_EQ(kDecodeBufferSize
, decode_size
);
411 // The resource generates uids internally, starting at 1.
413 ASSERT_EQ(uid
, decode_id
);
415 // Once we've allocated the maximum number of buffers, we must wait.
416 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(7U, kDecodeBufferSize
);
417 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
418 CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
419 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
420 ASSERT_EQ(7U, shm_id
);
421 ASSERT_EQ(kDecodeBufferSize
, decode_size
);
423 // Calling Decode when another Decode is pending should fail.
424 ASSERT_EQ(PP_ERROR_INPROGRESS
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
425 ASSERT_FALSE(uncalled_cb
.called());
426 // Free up the first decode buffer.
427 SendDecodeReply(params
, 0U);
428 // The decoder should run the pending callback.
429 ASSERT_TRUE(decode_cb
.called());
430 ASSERT_EQ(PP_OK
, decode_cb
.result());
433 // Now try to get a picture. No picture ready message has been received yet.
434 PP_VideoPicture picture
;
435 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
436 CallGetPicture(decoder
.get(), &picture
, &get_picture_cb
));
437 ASSERT_FALSE(get_picture_cb
.called());
438 // Calling GetPicture when another GetPicture is pending should fail.
439 ASSERT_EQ(PP_ERROR_INPROGRESS
,
440 CallGetPicture(decoder
.get(), &picture
, &uncalled_cb
));
441 ASSERT_FALSE(uncalled_cb
.called());
442 // Send 'request textures' message to initialize textures.
443 SendRequestTextures(params
);
444 // Send a picture ready message for Decode call 1. The GetPicture callback
446 SendPictureReady(params
, 1U, kTextureId1
);
447 ASSERT_TRUE(get_picture_cb
.called());
448 ASSERT_EQ(PP_OK
, get_picture_cb
.result());
449 ASSERT_EQ(kDecodeId
, picture
.decode_id
);
450 get_picture_cb
.Reset();
452 // Send a picture ready message for Decode call 2. Since there is no pending
453 // GetPicture call, the picture should be queued.
454 SendPictureReady(params
, 2U, kTextureId2
);
455 // The next GetPicture should return synchronously.
456 ASSERT_EQ(PP_OK
, CallGetPicture(decoder
.get(), &picture
, &uncalled_cb
));
457 ASSERT_FALSE(uncalled_cb
.called());
458 ASSERT_EQ(kDecodeId
, picture
.decode_id
);
460 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
462 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
463 // message for GetShm isn't received, causing Decode to fail.
464 // http://crbug.com/379260
465 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
466 TEST_F(VideoDecoderResourceTest
, RecyclePicture
) {
467 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
468 ResourceMessageCallParams params
;
469 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
471 // Get to a state where we have a picture to recycle.
472 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(0U, kDecodeBufferSize
);
473 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
475 uint32_t decode_size
;
477 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
478 SendDecodeReply(params
, 0U);
479 // Send 'request textures' message to initialize textures.
480 SendRequestTextures(params
);
481 // Call GetPicture and send 'picture ready' message to get a picture to
483 PP_VideoPicture picture
;
484 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
485 CallGetPicture(decoder
.get(), &picture
, &get_picture_cb
));
486 SendPictureReady(params
, 0U, kTextureId1
);
487 ASSERT_EQ(kTextureId1
, picture
.texture_id
);
489 CallRecyclePicture(decoder
.get(), picture
);
491 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms
, &texture_id
));
492 ASSERT_EQ(kTextureId1
, texture_id
);
494 ClearCallbacks(decoder
.get());
496 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
498 TEST_F(VideoDecoderResourceTest
, Flush
) {
499 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
500 ResourceMessageCallParams params
, params2
;
501 MockCompletionCallback flush_cb
, get_picture_cb
, uncalled_cb
;
503 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, CallFlush(decoder
.get(), &flush_cb
));
504 ASSERT_FALSE(flush_cb
.called());
505 ASSERT_TRUE(CheckFlushMsg(¶ms
));
507 ASSERT_EQ(PP_ERROR_FAILED
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
508 ASSERT_FALSE(uncalled_cb
.called());
510 // Plugin can call GetPicture while Flush is pending.
511 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
512 CallGetPicture(decoder
.get(), NULL
, &get_picture_cb
));
513 ASSERT_FALSE(get_picture_cb
.called());
515 ASSERT_EQ(PP_ERROR_INPROGRESS
, CallFlush(decoder
.get(), &uncalled_cb
));
516 ASSERT_FALSE(uncalled_cb
.called());
518 ASSERT_EQ(PP_ERROR_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
519 ASSERT_FALSE(uncalled_cb
.called());
521 // Plugin can call RecyclePicture while Flush is pending.
522 PP_VideoPicture picture
;
523 picture
.texture_id
= kTextureId1
;
524 CallRecyclePicture(decoder
.get(), picture
);
526 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms2
, &texture_id
));
528 SendFlushReply(params
);
529 // Any pending GetPicture call is aborted.
530 ASSERT_TRUE(get_picture_cb
.called());
531 ASSERT_EQ(PP_ERROR_ABORTED
, get_picture_cb
.result());
532 ASSERT_TRUE(flush_cb
.called());
533 ASSERT_EQ(PP_OK
, flush_cb
.result());
536 // TODO(bbudge) Test Reset when we can run the message loop to get aborted
539 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
540 // message for GetShm isn't received, causing Decode to fail.
541 // http://crbug.com/379260
542 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
543 TEST_F(VideoDecoderResourceTest
, NotifyError
) {
544 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
545 ResourceMessageCallParams params
;
546 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
548 // Call Decode and GetPicture to have some pending requests.
549 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(0U, kDecodeBufferSize
);
550 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
551 ASSERT_FALSE(decode_cb
.called());
552 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
553 CallGetPicture(decoder
.get(), NULL
, &get_picture_cb
));
554 ASSERT_FALSE(get_picture_cb
.called());
556 // Send the decoder resource an unsolicited notify error message. We first
557 // need to initialize 'params' so the message is routed to the decoder.
559 uint32_t decode_size
;
561 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
562 SendNotifyError(params
, PP_ERROR_RESOURCE_FAILED
);
564 // Any pending message should be run with the reported error.
565 ASSERT_TRUE(get_picture_cb
.called());
566 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, get_picture_cb
.result());
568 // All further calls return the reported error.
569 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
,
570 CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
571 ASSERT_FALSE(uncalled_cb
.called());
572 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
,
573 CallGetPicture(decoder
.get(), NULL
, &uncalled_cb
));
574 ASSERT_FALSE(uncalled_cb
.called());
575 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, CallFlush(decoder
.get(), &uncalled_cb
));
576 ASSERT_FALSE(uncalled_cb
.called());
577 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
578 ASSERT_FALSE(uncalled_cb
.called());
580 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)