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 const uint32_t kTextureId2
= 2;
35 const uint32_t kNumRequestedTextures
= 2;
37 class MockCompletionCallback
{
39 MockCompletionCallback() : called_(false) {}
41 bool called() { return called_
; }
42 int32_t result() { return result_
; }
44 void Reset() { called_
= false; }
46 static void Callback(void* user_data
, int32_t result
) {
47 MockCompletionCallback
* that
=
48 reinterpret_cast<MockCompletionCallback
*>(user_data
);
50 that
->result_
= result
;
58 class VideoDecoderResourceTest
: public PluginProxyTest
{
60 VideoDecoderResourceTest()
61 : decoder_iface_(thunk::GetPPB_VideoDecoder_0_2_Thunk()) {}
63 const PPB_VideoDecoder_0_2
* decoder_iface() const { return decoder_iface_
; }
65 void SendReply(const ResourceMessageCallParams
& params
,
67 const IPC::Message
& nested_message
) {
68 ResourceMessageReplyParams
reply_params(params
.pp_resource(),
70 reply_params
.set_result(result
);
71 PluginMessageFilter::DispatchResourceReplyForTest(reply_params
,
75 void SendReplyWithHandle(const ResourceMessageCallParams
& params
,
77 const IPC::Message
& nested_message
,
78 const SerializedHandle
& handle
) {
79 ResourceMessageReplyParams
reply_params(params
.pp_resource(),
81 reply_params
.set_result(result
);
82 reply_params
.AppendHandle(handle
);
83 PluginMessageFilter::DispatchResourceReplyForTest(reply_params
,
87 PP_Resource
CreateDecoder() {
88 PP_Resource result
= decoder_iface()->Create(pp_instance());
91 ppapi::Resource
* resource
=
92 GetGlobals()->GetResourceTracker()->GetResource(result
);
93 proxy::VideoDecoderResource
* decoder
=
94 static_cast<proxy::VideoDecoderResource
*>(resource
);
95 decoder
->SetForTest();
101 PP_Resource
CreateGraphics3d() {
104 HostResource host_resource
;
105 host_resource
.SetHostResource(pp_instance(), kGraphics3D
);
106 scoped_refptr
<ppapi::proxy::Graphics3D
> graphics_3d(
107 new ppapi::proxy::Graphics3D(host_resource
));
108 return graphics_3d
->GetReference();
111 PP_Resource
CreateAndInitializeDecoder() {
112 PP_Resource decoder
= CreateDecoder();
113 LockingResourceReleaser
graphics3d(CreateGraphics3d());
114 MockCompletionCallback cb
;
115 int32_t result
= decoder_iface()->Initialize(
118 PP_VIDEOPROFILE_H264MAIN
,
119 PP_HARDWAREACCELERATION_WITHFALLBACK
,
120 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
122 if (result
!= PP_OK_COMPLETIONPENDING
)
124 ResourceMessageCallParams params
;
126 if (!sink().GetFirstResourceCallMatching(
127 PpapiHostMsg_VideoDecoder_Initialize::ID
, ¶ms
, &msg
))
129 sink().ClearMessages();
130 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_InitializeReply());
134 int32_t CallDecode(PP_Resource pp_decoder
,
135 MockCompletionCallback
* cb
,
136 const PpapiHostMsg_VideoDecoder_GetShm
* expected_shm_msg
) {
137 // Set up a handler in case the resource sends a sync message to create
139 PpapiPluginMsg_VideoDecoder_GetShmReply
shm_msg_reply(kShmSize
);
140 ResourceSyncCallHandler
shm_msg_handler(
141 &sink(), PpapiHostMsg_VideoDecoder_GetShm::ID
, PP_OK
, shm_msg_reply
);
142 sink().AddFilter(&shm_msg_handler
);
144 base::SharedMemory shm
;
145 if (expected_shm_msg
) {
146 shm
.CreateAnonymous(kShmSize
);
147 base::SharedMemoryHandle shm_handle
;
148 shm
.ShareToProcess(base::GetCurrentProcessHandle(), &shm_handle
);
149 SerializedHandle
serialized_handle(shm_handle
, kShmSize
);
150 shm_msg_handler
.set_serialized_handle(&serialized_handle
);
153 memset(decode_buffer_
, 0x55, kDecodeBufferSize
);
155 decoder_iface()->Decode(pp_decoder
,
159 PP_MakeOptionalCompletionCallback(
160 &MockCompletionCallback::Callback
, cb
));
162 if (expected_shm_msg
) {
163 uint32_t shm_id
, shm_size
, expected_shm_id
, expected_shm_size
;
164 UnpackMessage
<PpapiHostMsg_VideoDecoder_GetShm
>(
165 *expected_shm_msg
, &expected_shm_id
, &expected_shm_size
);
166 if (shm_msg_handler
.last_handled_msg().type() == 0 ||
167 !UnpackMessage
<PpapiHostMsg_VideoDecoder_GetShm
>(
168 shm_msg_handler
.last_handled_msg(), &shm_id
, &shm_size
) ||
169 shm_id
!= expected_shm_id
||
170 shm_size
!= expected_shm_size
) {
171 // Signal that the expected shm message wasn't sent by failing.
172 result
= PP_ERROR_FAILED
;
176 sink().RemoveFilter(&shm_msg_handler
);
180 int32_t CallGetPicture(PP_Resource pp_decoder
,
181 PP_VideoPicture
* picture
,
182 MockCompletionCallback
* cb
) {
184 decoder_iface()->GetPicture(pp_decoder
,
186 PP_MakeOptionalCompletionCallback(
187 &MockCompletionCallback::Callback
, cb
));
191 void CallRecyclePicture(PP_Resource pp_decoder
,
192 const PP_VideoPicture
& picture
) {
193 decoder_iface()->RecyclePicture(pp_decoder
, &picture
);
196 int32_t CallFlush(PP_Resource pp_decoder
, MockCompletionCallback
* cb
) {
198 decoder_iface()->Flush(pp_decoder
,
199 PP_MakeOptionalCompletionCallback(
200 &MockCompletionCallback::Callback
, cb
));
204 int32_t CallReset(PP_Resource pp_decoder
, MockCompletionCallback
* cb
) {
206 decoder_iface()->Reset(pp_decoder
,
207 PP_MakeOptionalCompletionCallback(
208 &MockCompletionCallback::Callback
, cb
));
212 void SendDecodeReply(const ResourceMessageCallParams
& params
,
214 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_DecodeReply(shm_id
));
217 void SendPictureReady(const ResourceMessageCallParams
& params
,
218 uint32_t decode_count
,
219 uint32_t texture_id
) {
223 PpapiPluginMsg_VideoDecoder_PictureReady(decode_count
, texture_id
));
226 void SendFlushReply(const ResourceMessageCallParams
& params
) {
227 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_FlushReply());
230 void SendResetReply(const ResourceMessageCallParams
& params
) {
231 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_ResetReply());
234 void SendRequestTextures(const ResourceMessageCallParams
& params
) {
237 PpapiPluginMsg_VideoDecoder_RequestTextures(
238 kNumRequestedTextures
,
239 PP_MakeSize(320, 240),
241 std::vector
<gpu::Mailbox
>()));
244 void SendNotifyError(const ResourceMessageCallParams
& params
, int32_t error
) {
245 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_NotifyError(error
));
248 bool CheckDecodeMsg(ResourceMessageCallParams
* params
,
251 int32_t* decode_id
) {
253 if (!sink().GetFirstResourceCallMatching(
254 PpapiHostMsg_VideoDecoder_Decode::ID
, params
, &msg
))
256 sink().ClearMessages();
257 return UnpackMessage
<PpapiHostMsg_VideoDecoder_Decode
>(
258 msg
, shm_id
, size
, decode_id
);
261 bool CheckRecyclePictureMsg(ResourceMessageCallParams
* params
,
262 uint32_t* texture_id
) {
264 if (!sink().GetFirstResourceCallMatching(
265 PpapiHostMsg_VideoDecoder_RecyclePicture::ID
, params
, &msg
))
267 sink().ClearMessages();
268 return UnpackMessage
<PpapiHostMsg_VideoDecoder_RecyclePicture
>(msg
,
272 bool CheckFlushMsg(ResourceMessageCallParams
* params
) {
273 return CheckMsg(params
, PpapiHostMsg_VideoDecoder_Flush::ID
);
276 bool CheckResetMsg(ResourceMessageCallParams
* params
) {
277 return CheckMsg(params
, PpapiHostMsg_VideoDecoder_Reset::ID
);
280 void ClearCallbacks(PP_Resource pp_decoder
) {
281 ResourceMessageCallParams params
;
282 MockCompletionCallback cb
;
284 // Reset to abort Decode and GetPicture callbacks.
285 CallReset(pp_decoder
, &cb
);
286 // Initialize params so we can reply to the Reset.
287 CheckResetMsg(¶ms
);
288 // Run the Reset callback.
289 SendResetReply(params
);
293 bool CheckMsg(ResourceMessageCallParams
* params
, int id
) {
295 if (!sink().GetFirstResourceCallMatching(id
, params
, &msg
))
297 sink().ClearMessages();
301 const PPB_VideoDecoder_0_2
* decoder_iface_
;
303 char decode_buffer_
[kDecodeBufferSize
];
308 TEST_F(VideoDecoderResourceTest
, Initialize
) {
309 // Initialize with 0 graphics3d_context should fail.
311 LockingResourceReleaser
decoder(CreateDecoder());
312 MockCompletionCallback cb
;
313 int32_t result
= decoder_iface()->Initialize(
315 0 /* invalid 3d graphics */,
316 PP_VIDEOPROFILE_H264MAIN
,
317 PP_HARDWAREACCELERATION_WITHFALLBACK
,
318 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
320 ASSERT_EQ(PP_ERROR_BADRESOURCE
, result
);
322 // Initialize with bad profile value should fail.
324 LockingResourceReleaser
decoder(CreateDecoder());
325 MockCompletionCallback cb
;
326 int32_t result
= decoder_iface()->Initialize(
328 1 /* non-zero resource */,
329 static_cast<PP_VideoProfile
>(-1),
330 PP_HARDWAREACCELERATION_WITHFALLBACK
,
331 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
333 ASSERT_EQ(PP_ERROR_BADARGUMENT
, result
);
335 // Initialize with valid graphics3d_context and profile should succeed.
337 LockingResourceReleaser
decoder(CreateDecoder());
338 LockingResourceReleaser
graphics3d(CreateGraphics3d());
339 MockCompletionCallback cb
;
340 int32_t result
= decoder_iface()->Initialize(
343 PP_VIDEOPROFILE_H264MAIN
,
344 PP_HARDWAREACCELERATION_WITHFALLBACK
,
345 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
347 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, result
);
348 ASSERT_TRUE(decoder_iface()->IsVideoDecoder(decoder
.get()));
350 // Another attempt while pending should fail.
351 result
= decoder_iface()->Initialize(
354 PP_VIDEOPROFILE_H264MAIN
,
355 PP_HARDWAREACCELERATION_WITHFALLBACK
,
356 PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback
,
358 ASSERT_EQ(PP_ERROR_INPROGRESS
, result
);
360 // Check for host message and send a reply to complete initialization.
361 ResourceMessageCallParams params
;
363 ASSERT_TRUE(sink().GetFirstResourceCallMatching(
364 PpapiHostMsg_VideoDecoder_Initialize::ID
, ¶ms
, &msg
));
365 sink().ClearMessages();
366 SendReply(params
, PP_OK
, PpapiPluginMsg_VideoDecoder_InitializeReply());
367 ASSERT_TRUE(cb
.called());
368 ASSERT_EQ(PP_OK
, cb
.result());
372 TEST_F(VideoDecoderResourceTest
, Uninitialized
) {
373 // Operations on uninitialized decoders should fail.
374 LockingResourceReleaser
decoder(CreateDecoder());
375 MockCompletionCallback uncalled_cb
;
377 ASSERT_EQ(PP_ERROR_FAILED
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
378 ASSERT_FALSE(uncalled_cb
.called());
380 ASSERT_EQ(PP_ERROR_FAILED
, CallGetPicture(decoder
.get(), NULL
, &uncalled_cb
));
381 ASSERT_FALSE(uncalled_cb
.called());
383 ASSERT_EQ(PP_ERROR_FAILED
, CallFlush(decoder
.get(), &uncalled_cb
));
384 ASSERT_FALSE(uncalled_cb
.called());
386 ASSERT_EQ(PP_ERROR_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
387 ASSERT_FALSE(uncalled_cb
.called());
390 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
391 // message for GetShm isn't received, causing Decode to fail.
392 // http://crbug.com/379260
393 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
394 TEST_F(VideoDecoderResourceTest
, DecodeAndGetPicture
) {
395 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
396 ResourceMessageCallParams params
, params2
;
397 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
400 uint32_t decode_size
;
402 // Call Decode until we have the maximum pending, minus one.
403 for (uint32_t i
= 0; i
< kMaximumPendingDecodes
- 1; i
++) {
404 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(i
, kDecodeBufferSize
);
405 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &uncalled_cb
, &shm_msg
));
406 ASSERT_FALSE(uncalled_cb
.called());
407 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
408 ASSERT_EQ(i
, shm_id
);
409 ASSERT_EQ(kDecodeBufferSize
, decode_size
);
410 // The resource generates uids internally, starting at 1.
412 ASSERT_EQ(uid
, decode_id
);
414 // Once we've allocated the maximum number of buffers, we must wait.
415 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(7U, kDecodeBufferSize
);
416 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
417 CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
418 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
419 ASSERT_EQ(7U, shm_id
);
420 ASSERT_EQ(kDecodeBufferSize
, decode_size
);
422 // Calling Decode when another Decode is pending should fail.
423 ASSERT_EQ(PP_ERROR_INPROGRESS
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
424 ASSERT_FALSE(uncalled_cb
.called());
425 // Free up the first decode buffer.
426 SendDecodeReply(params
, 0U);
427 // The decoder should run the pending callback.
428 ASSERT_TRUE(decode_cb
.called());
429 ASSERT_EQ(PP_OK
, decode_cb
.result());
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 Decode call 1. The GetPicture callback
445 SendPictureReady(params
, 1U, kTextureId1
);
446 ASSERT_TRUE(get_picture_cb
.called());
447 ASSERT_EQ(PP_OK
, get_picture_cb
.result());
448 ASSERT_EQ(kDecodeId
, picture
.decode_id
);
449 get_picture_cb
.Reset();
451 // Send a picture ready message for Decode call 2. Since there is no pending
452 // GetPicture call, the picture should be queued.
453 SendPictureReady(params
, 2U, kTextureId2
);
454 // The next GetPicture should return synchronously.
455 ASSERT_EQ(PP_OK
, CallGetPicture(decoder
.get(), &picture
, &uncalled_cb
));
456 ASSERT_FALSE(uncalled_cb
.called());
457 ASSERT_EQ(kDecodeId
, picture
.decode_id
);
459 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
461 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
462 // message for GetShm isn't received, causing Decode to fail.
463 // http://crbug.com/379260
464 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
465 TEST_F(VideoDecoderResourceTest
, RecyclePicture
) {
466 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
467 ResourceMessageCallParams params
;
468 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
470 // Get to a state where we have a picture to recycle.
471 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(0U, kDecodeBufferSize
);
472 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
474 uint32_t decode_size
;
476 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
477 SendDecodeReply(params
, 0U);
478 // Send 'request textures' message to initialize textures.
479 SendRequestTextures(params
);
480 // Call GetPicture and send 'picture ready' message to get a picture to
482 PP_VideoPicture picture
;
483 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
484 CallGetPicture(decoder
.get(), &picture
, &get_picture_cb
));
485 SendPictureReady(params
, 0U, kTextureId1
);
486 ASSERT_EQ(kTextureId1
, picture
.texture_id
);
488 CallRecyclePicture(decoder
.get(), picture
);
490 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms
, &texture_id
));
491 ASSERT_EQ(kTextureId1
, texture_id
);
493 ClearCallbacks(decoder
.get());
495 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
497 TEST_F(VideoDecoderResourceTest
, Flush
) {
498 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
499 ResourceMessageCallParams params
, params2
;
500 MockCompletionCallback flush_cb
, get_picture_cb
, uncalled_cb
;
502 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, CallFlush(decoder
.get(), &flush_cb
));
503 ASSERT_FALSE(flush_cb
.called());
504 ASSERT_TRUE(CheckFlushMsg(¶ms
));
506 ASSERT_EQ(PP_ERROR_FAILED
, CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
507 ASSERT_FALSE(uncalled_cb
.called());
509 // Plugin can call GetPicture while Flush is pending.
510 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
511 CallGetPicture(decoder
.get(), NULL
, &get_picture_cb
));
512 ASSERT_FALSE(get_picture_cb
.called());
514 ASSERT_EQ(PP_ERROR_INPROGRESS
, CallFlush(decoder
.get(), &uncalled_cb
));
515 ASSERT_FALSE(uncalled_cb
.called());
517 ASSERT_EQ(PP_ERROR_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
518 ASSERT_FALSE(uncalled_cb
.called());
520 // Plugin can call RecyclePicture while Flush is pending.
521 PP_VideoPicture picture
;
522 picture
.texture_id
= kTextureId1
;
523 CallRecyclePicture(decoder
.get(), picture
);
525 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms2
, &texture_id
));
527 SendFlushReply(params
);
528 // Any pending GetPicture call is aborted.
529 ASSERT_TRUE(get_picture_cb
.called());
530 ASSERT_EQ(PP_ERROR_ABORTED
, get_picture_cb
.result());
531 ASSERT_TRUE(flush_cb
.called());
532 ASSERT_EQ(PP_OK
, flush_cb
.result());
535 // TODO(bbudge) Test Reset when we can run the message loop to get aborted
538 // TODO(bbudge) Fix sync message testing on Windows 64 bit builds. The reply
539 // message for GetShm isn't received, causing Decode to fail.
540 // http://crbug.com/379260
541 #if !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
542 TEST_F(VideoDecoderResourceTest
, NotifyError
) {
543 LockingResourceReleaser
decoder(CreateAndInitializeDecoder());
544 ResourceMessageCallParams params
;
545 MockCompletionCallback decode_cb
, get_picture_cb
, uncalled_cb
;
547 // Call Decode and GetPicture to have some pending requests.
548 PpapiHostMsg_VideoDecoder_GetShm
shm_msg(0U, kDecodeBufferSize
);
549 ASSERT_EQ(PP_OK
, CallDecode(decoder
.get(), &decode_cb
, &shm_msg
));
550 ASSERT_FALSE(decode_cb
.called());
551 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
552 CallGetPicture(decoder
.get(), NULL
, &get_picture_cb
));
553 ASSERT_FALSE(get_picture_cb
.called());
555 // Send the decoder resource an unsolicited notify error message. We first
556 // need to initialize 'params' so the message is routed to the decoder.
558 uint32_t decode_size
;
560 CheckDecodeMsg(¶ms
, &shm_id
, &decode_size
, &decode_id
);
561 SendNotifyError(params
, PP_ERROR_RESOURCE_FAILED
);
563 // Any pending message should be run with the reported error.
564 ASSERT_TRUE(get_picture_cb
.called());
565 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, get_picture_cb
.result());
567 // All further calls return the reported error.
568 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
,
569 CallDecode(decoder
.get(), &uncalled_cb
, NULL
));
570 ASSERT_FALSE(uncalled_cb
.called());
571 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
,
572 CallGetPicture(decoder
.get(), NULL
, &uncalled_cb
));
573 ASSERT_FALSE(uncalled_cb
.called());
574 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, CallFlush(decoder
.get(), &uncalled_cb
));
575 ASSERT_FALSE(uncalled_cb
.called());
576 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED
, CallReset(decoder
.get(), &uncalled_cb
));
577 ASSERT_FALSE(uncalled_cb
.called());
579 #endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)