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_1_Thunk()) {}
65 const PPB_VideoDecoder_1_1
* 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
,
123 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
125 if (result
!= PP_OK_COMPLETIONPENDING
)
127 ResourceMessageCallParams params
;
129 if (!sink().GetFirstResourceCallMatching(
130 PpapiHostMsg_VideoDecoder_Initialize::ID
, ¶ms
, &msg
))
132 sink().ClearMessages();
133 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_InitializeReply());
137 int32_t CallDecode(PP_Resource pp_decoder
,
138 MockCompletionCallback
* cb
,
139 const PpapiHostMsg_VideoDecoder_GetShm
* expected_shm_msg
) {
140 // Set up a handler in case the resource sends a sync message to create
142 PpapiPluginMsg_VideoDecoder_GetShmReply
shm_msg_reply(kShmSize
);
143 ResourceSyncCallHandler
shm_msg_handler(
144 &sink(), PpapiHostMsg_VideoDecoder_GetShm::ID
, PP_OK
, shm_msg_reply
);
145 sink().AddFilter(&shm_msg_handler
);
147 base::SharedMemory shm
;
148 if (expected_shm_msg
) {
149 shm
.CreateAnonymous(kShmSize
);
150 base::SharedMemoryHandle shm_handle
;
151 shm
.ShareToProcess(base::GetCurrentProcessHandle(), &shm_handle
);
152 SerializedHandle
serialized_handle(shm_handle
, kShmSize
);
153 shm_msg_handler
.set_serialized_handle(&serialized_handle
);
156 memset(decode_buffer_
, 0x55, kDecodeBufferSize
);
158 decoder_iface()->Decode(pp_decoder
,
162 PP_MakeOptionalCompletionCallback(
163 &MockCompletionCallback::Callback
, cb
));
165 if (expected_shm_msg
) {
166 uint32_t shm_id
, shm_size
, expected_shm_id
, expected_shm_size
;
167 UnpackMessage
<PpapiHostMsg_VideoDecoder_GetShm
>(
168 *expected_shm_msg
, &expected_shm_id
, &expected_shm_size
);
169 if (shm_msg_handler
.last_handled_msg().type() == 0 ||
170 !UnpackMessage
<PpapiHostMsg_VideoDecoder_GetShm
>(
171 shm_msg_handler
.last_handled_msg(), &shm_id
, &shm_size
) ||
172 shm_id
!= expected_shm_id
||
173 shm_size
!= expected_shm_size
) {
174 // Signal that the expected shm message wasn't sent by failing.
175 result
= PP_ERROR_FAILED
;
179 sink().RemoveFilter(&shm_msg_handler
);
183 int32_t CallGetPicture(PP_Resource pp_decoder
,
184 PP_VideoPicture
* picture
,
185 MockCompletionCallback
* cb
) {
187 decoder_iface()->GetPicture(pp_decoder
,
189 PP_MakeOptionalCompletionCallback(
190 &MockCompletionCallback::Callback
, cb
));
194 void CallRecyclePicture(PP_Resource pp_decoder
,
195 const PP_VideoPicture
& picture
) {
196 decoder_iface()->RecyclePicture(pp_decoder
, &picture
);
199 int32_t CallFlush(PP_Resource pp_decoder
, MockCompletionCallback
* cb
) {
201 decoder_iface()->Flush(pp_decoder
,
202 PP_MakeOptionalCompletionCallback(
203 &MockCompletionCallback::Callback
, cb
));
207 int32_t CallReset(PP_Resource pp_decoder
, MockCompletionCallback
* cb
) {
209 decoder_iface()->Reset(pp_decoder
,
210 PP_MakeOptionalCompletionCallback(
211 &MockCompletionCallback::Callback
, cb
));
215 void SendDecodeReply(const ResourceMessageCallParams
& params
,
217 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_DecodeReply(shm_id
));
220 void SendPictureReady(const ResourceMessageCallParams
& params
,
221 uint32_t decode_count
,
222 uint32_t texture_id
) {
223 PP_Rect visible_rect
= PP_MakeRectFromXYWH(0, 0, 640, 480);
224 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_PictureReady(
225 decode_count
, texture_id
, visible_rect
));
228 void SendFlushReply(const ResourceMessageCallParams
& params
) {
229 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_FlushReply());
232 void SendResetReply(const ResourceMessageCallParams
& params
) {
233 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_ResetReply());
236 void SendRequestTextures(const ResourceMessageCallParams
& params
) {
239 PpapiPluginMsg_VideoDecoder_RequestTextures(
240 kNumRequestedTextures
,
241 PP_MakeSize(320, 240),
243 std::vector
<gpu::Mailbox
>()));
246 void SendNotifyError(const ResourceMessageCallParams
& params
, int32_t error
) {
247 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_NotifyError(error
));
250 bool CheckDecodeMsg(ResourceMessageCallParams
* params
,
253 int32_t* decode_id
) {
255 if (!sink().GetFirstResourceCallMatching(
256 PpapiHostMsg_VideoDecoder_Decode::ID
, params
, &msg
))
258 sink().ClearMessages();
259 return UnpackMessage
<PpapiHostMsg_VideoDecoder_Decode
>(
260 msg
, shm_id
, size
, decode_id
);
263 bool CheckRecyclePictureMsg(ResourceMessageCallParams
* params
,
264 uint32_t* texture_id
) {
266 if (!sink().GetFirstResourceCallMatching(
267 PpapiHostMsg_VideoDecoder_RecyclePicture::ID
, params
, &msg
))
269 sink().ClearMessages();
270 return UnpackMessage
<PpapiHostMsg_VideoDecoder_RecyclePicture
>(msg
,
274 bool CheckFlushMsg(ResourceMessageCallParams
* params
) {
275 return CheckMsg(params
, PpapiHostMsg_VideoDecoder_Flush::ID
);
278 bool CheckResetMsg(ResourceMessageCallParams
* params
) {
279 return CheckMsg(params
, PpapiHostMsg_VideoDecoder_Reset::ID
);
282 void ClearCallbacks(PP_Resource pp_decoder
) {
283 ResourceMessageCallParams params
;
284 MockCompletionCallback cb
;
286 // Reset to abort Decode and GetPicture callbacks.
287 CallReset(pp_decoder
, &cb
);
288 // Initialize params so we can reply to the Reset.
289 CheckResetMsg(¶ms
);
290 // Run the Reset callback.
291 SendResetReply(params
);
295 bool CheckMsg(ResourceMessageCallParams
* params
, int id
) {
297 if (!sink().GetFirstResourceCallMatching(id
, params
, &msg
))
299 sink().ClearMessages();
303 const PPB_VideoDecoder_1_1
* decoder_iface_
;
305 char decode_buffer_
[kDecodeBufferSize
];
310 TEST_F(VideoDecoderResourceTest
, Initialize
) {
311 // Initialize with 0 graphics3d_context should fail.
313 LockingResourceReleaser
decoder(CreateDecoder());
314 MockCompletionCallback cb
;
315 int32_t result
= decoder_iface()->Initialize(
317 0 /* invalid 3d graphics */,
318 PP_VIDEOPROFILE_H264MAIN
,
319 PP_HARDWAREACCELERATION_WITHFALLBACK
,
321 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
323 ASSERT_EQ(PP_ERROR_BADRESOURCE
, result
);
325 // Initialize with bad profile value should fail.
327 LockingResourceReleaser
decoder(CreateDecoder());
328 MockCompletionCallback cb
;
329 int32_t result
= decoder_iface()->Initialize(
331 1 /* non-zero resource */,
332 static_cast<PP_VideoProfile
>(-1),
333 PP_HARDWAREACCELERATION_WITHFALLBACK
,
335 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
337 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
339 // Initialize with valid graphics3d_context and profile should succeed.
341 LockingResourceReleaser
decoder(CreateDecoder());
342 LockingResourceReleaser
graphics3d(CreateGraphics3d());
343 MockCompletionCallback cb
;
344 int32_t result
= decoder_iface()->Initialize(
347 PP_VIDEOPROFILE_H264MAIN
,
348 PP_HARDWAREACCELERATION_WITHFALLBACK
,
350 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
352 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
353 ASSERT_TRUE(decoder_iface()->IsVideoDecoder(decoder
.get()));
355 // Another attempt while pending should fail.
356 result
= decoder_iface()->Initialize(
359 PP_VIDEOPROFILE_H264MAIN
,
360 PP_HARDWAREACCELERATION_WITHFALLBACK
,
362 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
364 ASSERT_EQ(PP_ERROR_INPROGRESS
, result
);
366 // Check for host message and send a reply to complete initialization.
367 ResourceMessageCallParams params
;
369 ASSERT_TRUE(sink().GetFirstResourceCallMatching(
370 PpapiHostMsg_VideoDecoder_Initialize::ID
, ¶ms
, &msg
));
371 sink().ClearMessages();
372 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_InitializeReply());
373 ASSERT_TRUE(cb
.called());
374 ASSERT_EQ(PP_OK
, cb
.result());
378 TEST_F(VideoDecoderResourceTest
, Uninitialized
) {
379 // Operations on uninitialized decoders should fail.
380 LockingResourceReleaser
decoder(CreateDecoder());
381 MockCompletionCallback uncalled_cb
;
383 ASSERT_EQ(PP_ERROR_FAILED
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
384 ASSERT_FALSE(uncalled_cb
.called());
386 ASSERT_EQ(PP_ERROR_FAILED
, CallGetPicture(decoder
.get(), NULL
, &uncalled_cb
));
387 ASSERT_FALSE(uncalled_cb
.called());
389 ASSERT_EQ(PP_ERROR_FAILED
, CallFlush(decoder
.get(), &uncalled_cb
));
390 ASSERT_FALSE(uncalled_cb
.called());
392 ASSERT_EQ(PP_ERROR_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
393 ASSERT_FALSE(uncalled_cb
.called());
396 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
397 // message for GetShm isn't received, causing Decode to fail.
398 // http://crbug.com/379260
399 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
400 TEST_F(VideoDecoderResourceTest
, DecodeAndGetPicture
) {
401 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
402 ResourceMessageCallParams params
, params2
;
403 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
406 uint32_t decode_size
;
408 // Call Decode until we have the maximum pending, minus one.
409 for (uint32_t i
= 0; i
< kMaximumPendingDecodes
- 1; i
++) {
410 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(i
, kDecodeBufferSize
);
411 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &uncalled_cb
, &shm_msg
));
412 ASSERT_FALSE(uncalled_cb
.called());
413 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
414 ASSERT_EQ(i
, shm_id
);
415 ASSERT_EQ(kDecodeBufferSize
, decode_size
);
416 // The resource generates uids internally, starting at 1.
418 ASSERT_EQ(uid
, decode_id
);
420 // Once we've allocated the maximum number of buffers, we must wait.
421 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(7U, kDecodeBufferSize
);
422 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
423 CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
424 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
425 ASSERT_EQ(7U, shm_id
);
426 ASSERT_EQ(kDecodeBufferSize
, decode_size
);
428 // Calling Decode when another Decode is pending should fail.
429 ASSERT_EQ(PP_ERROR_INPROGRESS
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
430 ASSERT_FALSE(uncalled_cb
.called());
431 // Free up the first decode buffer.
432 SendDecodeReply(params
, 0U);
433 // The decoder should run the pending callback.
434 ASSERT_TRUE(decode_cb
.called());
435 ASSERT_EQ(PP_OK
, decode_cb
.result());
438 // Now try to get a picture. No picture ready message has been received yet.
439 PP_VideoPicture picture
;
440 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
441 CallGetPicture(decoder
.get(), &picture
, &get_picture_cb
));
442 ASSERT_FALSE(get_picture_cb
.called());
443 // Calling GetPicture when another GetPicture is pending should fail.
444 ASSERT_EQ(PP_ERROR_INPROGRESS
,
445 CallGetPicture(decoder
.get(), &picture
, &uncalled_cb
));
446 ASSERT_FALSE(uncalled_cb
.called());
447 // Send 'request textures' message to initialize textures.
448 SendRequestTextures(params
);
449 // Send a picture ready message for Decode call 1. The GetPicture callback
451 SendPictureReady(params
, 1U, kTextureId1
);
452 ASSERT_TRUE(get_picture_cb
.called());
453 ASSERT_EQ(PP_OK
, get_picture_cb
.result());
454 ASSERT_EQ(kDecodeId
, picture
.decode_id
);
455 get_picture_cb
.Reset();
457 // Send a picture ready message for Decode call 2. Since there is no pending
458 // GetPicture call, the picture should be queued.
459 SendPictureReady(params
, 2U, kTextureId2
);
460 // The next GetPicture should return synchronously.
461 ASSERT_EQ(PP_OK
, CallGetPicture(decoder
.get(), &picture
, &uncalled_cb
));
462 ASSERT_FALSE(uncalled_cb
.called());
463 ASSERT_EQ(kDecodeId
, picture
.decode_id
);
465 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
467 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
468 // message for GetShm isn't received, causing Decode to fail.
469 // http://crbug.com/379260
470 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
471 TEST_F(VideoDecoderResourceTest
, RecyclePicture
) {
472 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
473 ResourceMessageCallParams params
;
474 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
476 // Get to a state where we have a picture to recycle.
477 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(0U, kDecodeBufferSize
);
478 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
480 uint32_t decode_size
;
482 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
483 SendDecodeReply(params
, 0U);
484 // Send 'request textures' message to initialize textures.
485 SendRequestTextures(params
);
486 // Call GetPicture and send 'picture ready' message to get a picture to
488 PP_VideoPicture picture
;
489 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
490 CallGetPicture(decoder
.get(), &picture
, &get_picture_cb
));
491 SendPictureReady(params
, 0U, kTextureId1
);
492 ASSERT_EQ(kTextureId1
, picture
.texture_id
);
494 CallRecyclePicture(decoder
.get(), picture
);
496 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms
, &texture_id
));
497 ASSERT_EQ(kTextureId1
, texture_id
);
499 ClearCallbacks(decoder
.get());
501 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
503 TEST_F(VideoDecoderResourceTest
, Flush
) {
504 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
505 ResourceMessageCallParams params
, params2
;
506 MockCompletionCallback flush_cb
, get_picture_cb
, uncalled_cb
;
508 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, CallFlush(decoder
.get(), &flush_cb
));
509 ASSERT_FALSE(flush_cb
.called());
510 ASSERT_TRUE(CheckFlushMsg(¶ms
));
512 ASSERT_EQ(PP_ERROR_FAILED
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
513 ASSERT_FALSE(uncalled_cb
.called());
515 // Plugin can call GetPicture while Flush is pending.
516 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
517 CallGetPicture(decoder
.get(), NULL
, &get_picture_cb
));
518 ASSERT_FALSE(get_picture_cb
.called());
520 ASSERT_EQ(PP_ERROR_INPROGRESS
, CallFlush(decoder
.get(), &uncalled_cb
));
521 ASSERT_FALSE(uncalled_cb
.called());
523 ASSERT_EQ(PP_ERROR_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
524 ASSERT_FALSE(uncalled_cb
.called());
526 // Plugin can call RecyclePicture while Flush is pending.
527 PP_VideoPicture picture
;
528 picture
.texture_id
= kTextureId1
;
529 CallRecyclePicture(decoder
.get(), picture
);
531 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms2
, &texture_id
));
533 SendFlushReply(params
);
534 // Any pending GetPicture call is aborted.
535 ASSERT_TRUE(get_picture_cb
.called());
536 ASSERT_EQ(PP_ERROR_ABORTED
, get_picture_cb
.result());
537 ASSERT_TRUE(flush_cb
.called());
538 ASSERT_EQ(PP_OK
, flush_cb
.result());
541 // TODO(bbudge) Test Reset when we can run the message loop to get aborted
544 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
545 // message for GetShm isn't received, causing Decode to fail.
546 // http://crbug.com/379260
547 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
548 TEST_F(VideoDecoderResourceTest
, NotifyError
) {
549 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
550 ResourceMessageCallParams params
;
551 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
553 // Call Decode and GetPicture to have some pending requests.
554 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(0U, kDecodeBufferSize
);
555 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
556 ASSERT_FALSE(decode_cb
.called());
557 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
558 CallGetPicture(decoder
.get(), NULL
, &get_picture_cb
));
559 ASSERT_FALSE(get_picture_cb
.called());
561 // Send the decoder resource an unsolicited notify error message. We first
562 // need to initialize 'params' so the message is routed to the decoder.
564 uint32_t decode_size
;
566 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
567 SendNotifyError(params
, PP_ERROR_RESOURCE_FAILED
);
569 // Any pending message should be run with the reported error.
570 ASSERT_TRUE(get_picture_cb
.called());
571 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, get_picture_cb
.result());
573 // All further calls return the reported error.
574 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
,
575 CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
576 ASSERT_FALSE(uncalled_cb
.called());
577 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
,
578 CallGetPicture(decoder
.get(), NULL
, &uncalled_cb
));
579 ASSERT_FALSE(uncalled_cb
.called());
580 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, CallFlush(decoder
.get(), &uncalled_cb
));
581 ASSERT_FALSE(uncalled_cb
.called());
582 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
583 ASSERT_FALSE(uncalled_cb
.called());
585 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)