Chromium Code Reviews| 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 size_t kDecodeBufferSize = 16; | |
| 31 const uint8_t kDecodeBufferElement = 0x55; | |
| 32 const uint32_t kDecodeId = 5; | |
| 33 const uint32_t kTextureId1 = 1; | |
| 34 const uint32_t kTextureId2 = 2; | |
| 35 const uint32_t kNumRequestedTextures = 2; | |
| 36 | |
| 37 class MockCompletionCallback { | |
| 38 public: | |
| 39 MockCompletionCallback() : called_(false) {} | |
| 40 | |
| 41 bool called() { return called_; } | |
| 42 int32_t result() { return result_; } | |
| 43 | |
| 44 void Reset() { called_ = false; } | |
| 45 | |
| 46 static void Callback(void* user_data, int32_t result) { | |
| 47 MockCompletionCallback* that = | |
| 48 reinterpret_cast<MockCompletionCallback*>(user_data); | |
| 49 that->called_ = true; | |
| 50 that->result_ = result; | |
| 51 } | |
| 52 | |
| 53 private: | |
| 54 bool called_; | |
| 55 int32_t result_; | |
| 56 }; | |
| 57 | |
| 58 class VideoDecoderResourceTest : public PluginProxyTest { | |
| 59 public: | |
| 60 const PPB_VideoDecoder_0_1* decoder_iface; | |
| 61 const PPB_Graphics3D_1_0* graphics3d_iface; | |
|
piman
2014/05/22 20:43:19
nit: order is methods, then fields (fields should
bbudge
2014/05/23 12:24:35
Done.
| |
| 62 | |
| 63 VideoDecoderResourceTest() | |
| 64 : decoder_iface(thunk::GetPPB_VideoDecoder_0_1_Thunk()), | |
| 65 graphics3d_iface(thunk::GetPPB_Graphics3D_1_0_Thunk()) {} | |
| 66 | |
| 67 void SendReply(const ResourceMessageCallParams& params, | |
| 68 int32_t result, | |
| 69 const IPC::Message& nested_message) { | |
| 70 ResourceMessageReplyParams reply_params(params.pp_resource(), | |
| 71 params.sequence()); | |
| 72 reply_params.set_result(result); | |
| 73 PluginMessageFilter::DispatchResourceReplyForTest(reply_params, | |
| 74 nested_message); | |
| 75 } | |
| 76 | |
| 77 void SendReplyWithHandle(const ResourceMessageCallParams& params, | |
| 78 int32_t result, | |
| 79 const IPC::Message& nested_message, | |
| 80 const SerializedHandle& handle) { | |
| 81 ResourceMessageReplyParams reply_params(params.pp_resource(), | |
| 82 params.sequence()); | |
| 83 reply_params.set_result(result); | |
| 84 reply_params.AppendHandle(handle); | |
| 85 PluginMessageFilter::DispatchResourceReplyForTest(reply_params, | |
| 86 nested_message); | |
| 87 } | |
| 88 | |
| 89 PP_Resource CreateDecoder() { | |
| 90 PP_Resource result = decoder_iface->Create(pp_instance()); | |
| 91 if (result) { | |
| 92 ProxyAutoLock lock; | |
| 93 ppapi::Resource* resource = | |
| 94 GetGlobals()->GetResourceTracker()->GetResource(result); | |
| 95 proxy::VideoDecoderResource* decoder = | |
| 96 static_cast<proxy::VideoDecoderResource*>(resource); | |
| 97 decoder->SetForTest(); | |
| 98 } | |
| 99 | |
| 100 return result; | |
| 101 } | |
| 102 | |
| 103 PP_Resource CreateGraphics3d() { | |
| 104 ProxyAutoLock lock; | |
| 105 | |
| 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(); | |
| 111 } | |
| 112 | |
| 113 PP_Resource CreateAndInitializeDecoder() { | |
| 114 PP_Resource decoder = CreateDecoder(); | |
| 115 LockingResourceReleaser graphics3d(CreateGraphics3d()); | |
| 116 MockCompletionCallback cb; | |
| 117 int32_t result = | |
| 118 decoder_iface->Initialize(decoder, | |
| 119 graphics3d.get(), | |
| 120 PP_VIDEOPROFILE_H264MAIN, | |
| 121 PP_TRUE /* allow_software_fallback */, | |
| 122 PP_MakeOptionalCompletionCallback( | |
| 123 &MockCompletionCallback::Callback, &cb)); | |
| 124 if (result != PP_OK_COMPLETIONPENDING) | |
| 125 return 0; | |
| 126 ResourceMessageCallParams params; | |
| 127 IPC::Message msg; | |
| 128 if (!sink().GetFirstResourceCallMatching( | |
| 129 PpapiHostMsg_VideoDecoder_Initialize::ID, ¶ms, &msg)) | |
| 130 return 0; | |
| 131 sink().ClearMessages(); | |
| 132 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_InitializeReply()); | |
| 133 return decoder; | |
| 134 } | |
| 135 | |
| 136 SerializedHandle CreateSharedMemory(uint32_t size) { | |
| 137 base::SharedMemory shm; | |
| 138 shm.CreateAnonymous(size); | |
| 139 base::SharedMemoryHandle shm_handle; | |
| 140 shm.ShareToProcess(base::GetCurrentProcessHandle(), &shm_handle); | |
| 141 return SerializedHandle(shm_handle, size); | |
| 142 } | |
| 143 | |
| 144 int32_t CallDecode(PP_Resource pp_decoder, MockCompletionCallback* cb) { | |
| 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)); | |
| 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 SendCreatedShm(const ResourceMessageCallParams& params, uint32_t size) { | |
| 189 SendReplyWithHandle(params, | |
| 190 PP_OK, | |
| 191 PpapiPluginMsg_VideoDecoder_CreatedShm(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 decode_count, | |
| 202 uint32_t texture_id) { | |
| 203 SendReply(params, | |
| 204 PP_OK, | |
| 205 PpapiPluginMsg_VideoDecoder_PictureReady( | |
| 206 decode_count, texture_id)); | |
| 207 } | |
| 208 | |
| 209 void SendFlushReply(const ResourceMessageCallParams& params) { | |
| 210 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_FlushReply()); | |
| 211 } | |
| 212 | |
| 213 void SendResetReply(const ResourceMessageCallParams& params) { | |
| 214 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_ResetReply()); | |
| 215 } | |
| 216 | |
| 217 void SendRequestTextures(const ResourceMessageCallParams& params) { | |
| 218 SendReply(params, | |
| 219 PP_OK, | |
| 220 PpapiPluginMsg_VideoDecoder_RequestTextures( | |
| 221 kNumRequestedTextures, PP_MakeSize(320, 240), GL_TEXTURE_2D)); | |
| 222 } | |
| 223 | |
| 224 void SendNotifyError(const ResourceMessageCallParams& params, int32_t error) { | |
| 225 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_NotifyError(error)); | |
| 226 } | |
| 227 | |
| 228 bool CheckDecodeBufferMsg(ResourceMessageCallParams* params, | |
| 229 std::vector<uint8_t>* buffer, | |
| 230 uint32_t* pending_shm_id) { | |
| 231 IPC::Message msg; | |
| 232 if (!sink().GetFirstResourceCallMatching( | |
| 233 PpapiHostMsg_VideoDecoder_DecodeBuffer::ID, params, &msg)) | |
| 234 return false; | |
| 235 sink().ClearMessages(); | |
| 236 return UnpackMessage<PpapiHostMsg_VideoDecoder_DecodeBuffer>( | |
| 237 msg, buffer, pending_shm_id); | |
| 238 } | |
| 239 | |
| 240 bool CheckDecodeMsg(ResourceMessageCallParams* params, | |
| 241 uint32_t* shm_id, | |
| 242 uint32_t* size) { | |
| 243 IPC::Message msg; | |
| 244 if (!sink().GetFirstResourceCallMatching( | |
| 245 PpapiHostMsg_VideoDecoder_Decode::ID, params, &msg)) | |
| 246 return false; | |
| 247 sink().ClearMessages(); | |
| 248 return UnpackMessage<PpapiHostMsg_VideoDecoder_Decode>(msg, shm_id, size); | |
| 249 } | |
| 250 | |
| 251 bool CheckRecyclePictureMsg(ResourceMessageCallParams* params, | |
| 252 uint32_t* texture_id) { | |
| 253 IPC::Message msg; | |
| 254 if (!sink().GetFirstResourceCallMatching( | |
| 255 PpapiHostMsg_VideoDecoder_RecyclePicture::ID, params, &msg)) | |
| 256 return false; | |
| 257 sink().ClearMessages(); | |
| 258 return UnpackMessage<PpapiHostMsg_VideoDecoder_RecyclePicture>(msg, | |
| 259 texture_id); | |
| 260 } | |
| 261 | |
| 262 bool CheckFlushMsg(ResourceMessageCallParams* params) { | |
| 263 return CheckMsg(params, PpapiHostMsg_VideoDecoder_Flush::ID); | |
| 264 } | |
| 265 | |
| 266 bool CheckResetMsg(ResourceMessageCallParams* params) { | |
| 267 return CheckMsg(params, PpapiHostMsg_VideoDecoder_Reset::ID); | |
| 268 } | |
| 269 | |
| 270 void ClearCallbacks(PP_Resource pp_decoder) { | |
| 271 ResourceMessageCallParams params; | |
| 272 MockCompletionCallback cb; | |
| 273 | |
| 274 // Reset to abort Decode and GetPicture callbacks. | |
| 275 CallReset(pp_decoder, &cb); | |
| 276 // Initialize params so we can reply to the Reset. | |
| 277 CheckResetMsg(¶ms); | |
| 278 // Run the Reset callback. | |
| 279 SendResetReply(params); | |
| 280 } | |
| 281 | |
| 282 char decode_buffer[kDecodeBufferSize]; | |
| 283 | |
| 284 private: | |
| 285 bool CheckMsg(ResourceMessageCallParams* params, int id) { | |
| 286 IPC::Message msg; | |
| 287 if (!sink().GetFirstResourceCallMatching(id, params, &msg)) | |
| 288 return false; | |
| 289 sink().ClearMessages(); | |
| 290 return true; | |
| 291 } | |
| 292 }; | |
| 293 | |
| 294 } // namespace | |
| 295 | |
| 296 TEST_F(VideoDecoderResourceTest, Initialize) { | |
| 297 // Initialize with 0 graphics3d_context should fail. | |
| 298 { | |
| 299 LockingResourceReleaser decoder(CreateDecoder()); | |
| 300 MockCompletionCallback cb; | |
| 301 int32_t result = | |
| 302 decoder_iface->Initialize(decoder.get(), | |
| 303 0 /* invalid 3d graphics */, | |
| 304 PP_VIDEOPROFILE_H264MAIN, | |
| 305 kAllowSoftwareFallback, | |
| 306 PP_MakeOptionalCompletionCallback( | |
| 307 &MockCompletionCallback::Callback, &cb)); | |
| 308 ASSERT_EQ(PP_ERROR_BADRESOURCE, result); | |
| 309 } | |
| 310 // Initialize with bad profile value should fail. | |
| 311 { | |
| 312 LockingResourceReleaser decoder(CreateDecoder()); | |
| 313 MockCompletionCallback cb; | |
| 314 int32_t result = | |
| 315 decoder_iface->Initialize(decoder.get(), | |
| 316 1 /* non-zero resource */, | |
| 317 static_cast<PP_VideoProfile>(-1), | |
| 318 kAllowSoftwareFallback, | |
| 319 PP_MakeOptionalCompletionCallback( | |
| 320 &MockCompletionCallback::Callback, &cb)); | |
| 321 ASSERT_EQ(PP_ERROR_BADARGUMENT, result); | |
| 322 } | |
| 323 // Initialize with valid graphics3d_context and profile should succeed. | |
| 324 { | |
| 325 LockingResourceReleaser decoder(CreateDecoder()); | |
| 326 LockingResourceReleaser graphics3d(CreateGraphics3d()); | |
| 327 MockCompletionCallback cb; | |
| 328 int32_t result = | |
| 329 decoder_iface->Initialize(decoder.get(), | |
| 330 graphics3d.get(), | |
| 331 PP_VIDEOPROFILE_H264MAIN, | |
| 332 kAllowSoftwareFallback, | |
| 333 PP_MakeOptionalCompletionCallback( | |
| 334 &MockCompletionCallback::Callback, &cb)); | |
| 335 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result); | |
| 336 ASSERT_TRUE(decoder_iface->IsVideoDecoder(decoder.get())); | |
| 337 | |
| 338 // Another attempt while pending should fail. | |
| 339 result = | |
| 340 decoder_iface->Initialize(decoder.get(), | |
| 341 graphics3d.get(), | |
| 342 PP_VIDEOPROFILE_H264MAIN, | |
| 343 kAllowSoftwareFallback, | |
| 344 PP_MakeOptionalCompletionCallback( | |
| 345 &MockCompletionCallback::Callback, &cb)); | |
| 346 ASSERT_EQ(PP_ERROR_INPROGRESS, result); | |
| 347 | |
| 348 // Check for host message and send a reply to complete initialization. | |
| 349 ResourceMessageCallParams params; | |
| 350 IPC::Message msg; | |
| 351 ASSERT_TRUE(sink().GetFirstResourceCallMatching( | |
| 352 PpapiHostMsg_VideoDecoder_Initialize::ID, ¶ms, &msg)); | |
| 353 sink().ClearMessages(); | |
| 354 SendReply(params, PP_OK, PpapiPluginMsg_VideoDecoder_InitializeReply()); | |
| 355 ASSERT_TRUE(cb.called()); | |
| 356 ASSERT_EQ(PP_OK, cb.result()); | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 TEST_F(VideoDecoderResourceTest, Uninitialized) { | |
| 361 // Operations on uninitialized decoders should fail. | |
| 362 LockingResourceReleaser decoder(CreateDecoder()); | |
| 363 MockCompletionCallback uncalled_cb; | |
| 364 | |
| 365 ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb)); | |
| 366 ASSERT_FALSE(uncalled_cb.called()); | |
| 367 | |
| 368 ASSERT_EQ(PP_ERROR_FAILED, CallGetPicture(decoder.get(), NULL, &uncalled_cb)); | |
| 369 ASSERT_FALSE(uncalled_cb.called()); | |
| 370 | |
| 371 ASSERT_EQ(PP_ERROR_FAILED, CallFlush(decoder.get(), &uncalled_cb)); | |
| 372 ASSERT_FALSE(uncalled_cb.called()); | |
| 373 | |
| 374 ASSERT_EQ(PP_ERROR_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
| 375 ASSERT_FALSE(uncalled_cb.called()); | |
| 376 } | |
| 377 | |
| 378 TEST_F(VideoDecoderResourceTest, DecodeAndGetPicture) { | |
| 379 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
| 380 ResourceMessageCallParams params, params2; | |
| 381 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
| 382 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallDecode(decoder.get(), &decode_cb)); | |
| 383 ASSERT_FALSE(decode_cb.called()); | |
| 384 | |
| 385 // Calling Decode when another Decode is pending should fail. | |
| 386 ASSERT_EQ(PP_ERROR_INPROGRESS, CallDecode(decoder.get(), &uncalled_cb)); | |
| 387 ASSERT_FALSE(uncalled_cb.called()); | |
| 388 | |
| 389 // Check for host message DecodeBuffer. | |
| 390 std::vector<uint8_t> buffer; | |
| 391 uint32_t shm_id; | |
| 392 uint32_t decode_size; | |
| 393 CheckDecodeBufferMsg(¶ms, &buffer, &shm_id); | |
| 394 ASSERT_EQ(buffer.size(), kDecodeBufferSize); | |
| 395 ASSERT_EQ(kDecodeBufferElement, buffer[0]); | |
| 396 ASSERT_EQ(kDecodeBufferElement, buffer[kDecodeBufferSize - 1]); | |
| 397 ASSERT_EQ(0U, shm_id); | |
| 398 // Send CreatedShm reply with a handle, and DecodeReply. | |
| 399 SendCreatedShm(params, 2 * kDecodeBufferSize); | |
| 400 ASSERT_FALSE(decode_cb.called()); | |
| 401 SendDecodeReply(params, 0U); | |
| 402 // The decoder should run the callback. | |
| 403 ASSERT_TRUE(decode_cb.called()); | |
| 404 ASSERT_EQ(PP_OK, decode_cb.result()); | |
| 405 decode_cb.Reset(); | |
| 406 | |
| 407 // The decoder has a shm buffer and it is available. The next Decode call | |
| 408 // should use it and complete synchronously. | |
| 409 ASSERT_EQ(PP_OK, CallDecode(decoder.get(), &decode_cb)); | |
| 410 ASSERT_FALSE(decode_cb.called()); | |
| 411 // Check for host message Decode. | |
| 412 ASSERT_TRUE(CheckDecodeMsg(¶ms, &shm_id, &decode_size)); | |
| 413 ASSERT_EQ(0U, shm_id); | |
| 414 ASSERT_EQ(kDecodeBufferSize, decode_size); | |
| 415 | |
| 416 // Now try to get a picture. No picture ready message has been received yet. | |
| 417 PP_VideoPicture picture; | |
| 418 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
| 419 CallGetPicture(decoder.get(), &picture, &get_picture_cb)); | |
| 420 ASSERT_FALSE(get_picture_cb.called()); | |
| 421 // Calling GetPicture when another GetPicture is pending should fail. | |
| 422 ASSERT_EQ(PP_ERROR_INPROGRESS, | |
| 423 CallGetPicture(decoder.get(), &picture, &uncalled_cb)); | |
| 424 ASSERT_FALSE(uncalled_cb.called()); | |
| 425 // Send 'request textures' message to initialize textures. | |
| 426 SendRequestTextures(params); | |
| 427 // Send a picture ready message for Decode call 0. The GetPicture callback | |
| 428 // should complete. | |
| 429 SendPictureReady(params, 0U, kTextureId1); | |
| 430 ASSERT_TRUE(get_picture_cb.called()); | |
| 431 ASSERT_EQ(PP_OK, get_picture_cb.result()); | |
| 432 ASSERT_EQ(kDecodeId, picture.decode_id); | |
| 433 get_picture_cb.Reset(); | |
| 434 | |
| 435 // Send a picture ready message for Decode call 1. Since there is no pending | |
| 436 // GetPicture call, the picture should be queued. | |
| 437 SendPictureReady(params, 1U, kTextureId2); | |
| 438 // The next GetPicture should return synchronously. | |
| 439 ASSERT_EQ(PP_OK, CallGetPicture(decoder.get(), &picture, &uncalled_cb)); | |
| 440 ASSERT_FALSE(uncalled_cb.called()); | |
| 441 ASSERT_EQ(kDecodeId, picture.decode_id); | |
| 442 } | |
| 443 | |
| 444 TEST_F(VideoDecoderResourceTest, RecyclePicture) { | |
| 445 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
| 446 ResourceMessageCallParams params; | |
| 447 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
| 448 | |
| 449 // Get to a state where we have a picture to recycle. | |
| 450 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallDecode(decoder.get(), &decode_cb)); | |
| 451 ASSERT_FALSE(decode_cb.called()); | |
| 452 std::vector<uint8_t> buffer; | |
| 453 uint32_t pending_shm_id; | |
| 454 CheckDecodeBufferMsg(¶ms, &buffer, &pending_shm_id); | |
| 455 SendCreatedShm(params, 2 * kDecodeBufferSize); | |
| 456 SendDecodeReply(params, 0U); | |
| 457 // Send 'request textures' message to initialize textures. | |
| 458 SendRequestTextures(params); | |
| 459 // Call GetPicture and send 'picture ready' message to get a picture to | |
| 460 // recycle. | |
| 461 PP_VideoPicture picture; | |
| 462 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
| 463 CallGetPicture(decoder.get(), &picture, &get_picture_cb)); | |
| 464 SendPictureReady(params, 0U, kTextureId1); | |
| 465 ASSERT_EQ(kTextureId1, picture.texture_id); | |
| 466 | |
| 467 CallRecyclePicture(decoder.get(), picture); | |
| 468 uint32_t texture_id; | |
| 469 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms, &texture_id)); | |
| 470 ASSERT_EQ(kTextureId1, texture_id); | |
| 471 | |
| 472 ClearCallbacks(decoder.get()); | |
| 473 } | |
| 474 | |
| 475 TEST_F(VideoDecoderResourceTest, Flush) { | |
| 476 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
| 477 ResourceMessageCallParams params, params2; | |
| 478 MockCompletionCallback flush_cb, get_picture_cb, uncalled_cb; | |
| 479 | |
| 480 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallFlush(decoder.get(), &flush_cb)); | |
| 481 ASSERT_FALSE(flush_cb.called()); | |
| 482 ASSERT_TRUE(CheckFlushMsg(¶ms)); | |
| 483 | |
| 484 ASSERT_EQ(PP_ERROR_FAILED, CallDecode(decoder.get(), &uncalled_cb)); | |
| 485 ASSERT_FALSE(uncalled_cb.called()); | |
| 486 | |
| 487 // Plugin can call GetPicture while Flush is pending. | |
| 488 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
| 489 CallGetPicture(decoder.get(), NULL, &get_picture_cb)); | |
| 490 ASSERT_FALSE(get_picture_cb.called()); | |
| 491 | |
| 492 ASSERT_EQ(PP_ERROR_INPROGRESS, CallFlush(decoder.get(), &uncalled_cb)); | |
| 493 ASSERT_FALSE(uncalled_cb.called()); | |
| 494 | |
| 495 ASSERT_EQ(PP_ERROR_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
| 496 ASSERT_FALSE(uncalled_cb.called()); | |
| 497 | |
| 498 // Plugin can call RecyclePicture while Flush is pending. | |
| 499 PP_VideoPicture picture; | |
| 500 picture.texture_id = kTextureId1; | |
| 501 CallRecyclePicture(decoder.get(), picture); | |
| 502 uint32_t texture_id; | |
| 503 ASSERT_TRUE(CheckRecyclePictureMsg(¶ms2, &texture_id)); | |
| 504 | |
| 505 SendFlushReply(params); | |
| 506 // Any pending GetPicture call is aborted. | |
| 507 ASSERT_TRUE(get_picture_cb.called()); | |
| 508 ASSERT_EQ(PP_ERROR_ABORTED, get_picture_cb.result()); | |
| 509 ASSERT_TRUE(flush_cb.called()); | |
| 510 ASSERT_EQ(PP_OK, flush_cb.result()); | |
| 511 } | |
| 512 | |
| 513 // TODO(bbudge) Test Reset when we can run the message loop to get aborted | |
| 514 // callbacks to run. | |
| 515 | |
| 516 TEST_F(VideoDecoderResourceTest, NotifyError) { | |
| 517 LockingResourceReleaser decoder(CreateAndInitializeDecoder()); | |
| 518 ResourceMessageCallParams params; | |
| 519 MockCompletionCallback decode_cb, get_picture_cb, uncalled_cb; | |
| 520 | |
| 521 // Call Decode and GetPicture to have some pending requests. | |
| 522 ASSERT_EQ(PP_OK_COMPLETIONPENDING, CallDecode(decoder.get(), &decode_cb)); | |
| 523 ASSERT_FALSE(decode_cb.called()); | |
| 524 ASSERT_EQ(PP_OK_COMPLETIONPENDING, | |
| 525 CallGetPicture(decoder.get(), NULL, &get_picture_cb)); | |
| 526 ASSERT_FALSE(get_picture_cb.called()); | |
| 527 | |
| 528 // Send the decoder resource an unsolicited notify error message. We first | |
| 529 // need to initialize 'params' so the message is routed to the decoder. | |
| 530 std::vector<uint8_t> buffer; | |
| 531 uint32_t pending_shm_id; | |
| 532 CheckDecodeBufferMsg(¶ms, &buffer, &pending_shm_id); | |
| 533 SendNotifyError(params, PP_ERROR_RESOURCE_FAILED); | |
| 534 | |
| 535 // Both pending messages should be run with the reported error. | |
| 536 ASSERT_TRUE(decode_cb.called()); | |
| 537 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, decode_cb.result()); | |
| 538 ASSERT_TRUE(get_picture_cb.called()); | |
| 539 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, get_picture_cb.result()); | |
| 540 | |
| 541 // All further calls return the reported error. | |
| 542 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, CallDecode(decoder.get(), &uncalled_cb)); | |
| 543 ASSERT_FALSE(uncalled_cb.called()); | |
| 544 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, | |
| 545 CallGetPicture(decoder.get(), NULL, &uncalled_cb)); | |
| 546 ASSERT_FALSE(uncalled_cb.called()); | |
| 547 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, CallFlush(decoder.get(), &uncalled_cb)); | |
| 548 ASSERT_FALSE(uncalled_cb.called()); | |
| 549 ASSERT_EQ(PP_ERROR_RESOURCE_FAILED, CallReset(decoder.get(), &uncalled_cb)); | |
| 550 ASSERT_FALSE(uncalled_cb.called()); | |
| 551 } | |
| 552 | |
| 553 } // namespace proxy | |
| 554 } // namespace ppapi | |
| OLD | NEW |