1 #include <android/log.h> 2 #include <android/native_window.h> 3 #include <dvr/dvr_api.h> 4 #include <dvr/dvr_buffer_queue.h> 5 6 #include <gtest/gtest.h> 7 8 #include <array> 9 #include <unordered_map> 10 11 #include "dvr_api_test.h" 12 13 #define LOG_TAG "dvr_buffer_queue-test" 14 15 #ifndef ALOGD 16 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 17 #endif 18 19 #ifndef ALOGD_IF 20 #define ALOGD_IF(cond, ...) \ 21 ((__predict_false(cond)) ? ((void)ALOGD(__VA_ARGS__)) : (void)0) 22 #endif 23 24 namespace { 25 26 static constexpr uint32_t kBufferWidth = 100; 27 static constexpr uint32_t kBufferHeight = 1; 28 static constexpr uint32_t kLayerCount = 1; 29 static constexpr uint32_t kBufferFormat = AHARDWAREBUFFER_FORMAT_BLOB; 30 static constexpr uint64_t kBufferUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN; 31 static constexpr size_t kQueueCapacity = 3; 32 33 class DvrBufferQueueTest : public DvrApiTest { 34 public: 35 static void BufferAvailableCallback(void* context) { 36 DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context); 37 thiz->HandleBufferAvailable(); 38 } 39 40 static void BufferRemovedCallback(DvrReadBuffer* buffer, void* context) { 41 DvrBufferQueueTest* thiz = static_cast<DvrBufferQueueTest*>(context); 42 thiz->HandleBufferRemoved(buffer); 43 } 44 45 protected: 46 void TearDown() override { 47 if (write_queue_ != nullptr) { 48 api_.WriteBufferQueueDestroy(write_queue_); 49 write_queue_ = nullptr; 50 } 51 DvrApiTest::TearDown(); 52 } 53 54 void HandleBufferAvailable() { 55 buffer_available_count_ += 1; 56 ALOGD_IF(TRACE, "Buffer avaiable, count=%d", buffer_available_count_); 57 } 58 59 void HandleBufferRemoved(DvrReadBuffer* buffer) { 60 buffer_removed_count_ += 1; 61 ALOGD_IF(TRACE, "Buffer removed, buffer=%p, count=%d", buffer, 62 buffer_removed_count_); 63 } 64 65 DvrWriteBufferQueue* write_queue_{nullptr}; 66 int buffer_available_count_{0}; 67 int buffer_removed_count_{0}; 68 }; 69 70 TEST_F(DvrBufferQueueTest, WriteQueueCreateDestroy) { 71 int ret = api_.WriteBufferQueueCreate( 72 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 73 /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_); 74 ASSERT_EQ(0, ret); 75 76 api_.WriteBufferQueueDestroy(write_queue_); 77 write_queue_ = nullptr; 78 } 79 80 TEST_F(DvrBufferQueueTest, WriteQueueGetCapacity) { 81 int ret = api_.WriteBufferQueueCreate( 82 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 83 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); 84 ASSERT_EQ(0, ret); 85 86 size_t capacity = api_.WriteBufferQueueGetCapacity(write_queue_); 87 88 ALOGD_IF(TRACE, "TestWrite_QueueGetCapacity, capacity=%zu", capacity); 89 ASSERT_EQ(kQueueCapacity, capacity); 90 } 91 92 TEST_F(DvrBufferQueueTest, CreateReadQueueFromWriteQueue) { 93 int ret = api_.WriteBufferQueueCreate( 94 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 95 /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_); 96 ASSERT_EQ(0, ret); 97 98 DvrReadBufferQueue* read_queue = nullptr; 99 ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue); 100 101 ASSERT_EQ(0, ret); 102 ASSERT_NE(nullptr, read_queue); 103 104 api_.ReadBufferQueueDestroy(read_queue); 105 } 106 107 TEST_F(DvrBufferQueueTest, CreateReadQueueFromReadQueue) { 108 int ret = api_.WriteBufferQueueCreate( 109 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 110 /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_); 111 ASSERT_EQ(0, ret); 112 113 DvrReadBufferQueue* read_queue1 = nullptr; 114 DvrReadBufferQueue* read_queue2 = nullptr; 115 ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue1); 116 117 ASSERT_EQ(0, ret); 118 ASSERT_NE(nullptr, read_queue1); 119 120 ret = api_.ReadBufferQueueCreateReadQueue(read_queue1, &read_queue2); 121 ASSERT_EQ(0, ret); 122 ASSERT_NE(nullptr, read_queue2); 123 ASSERT_NE(read_queue1, read_queue2); 124 125 api_.ReadBufferQueueDestroy(read_queue1); 126 api_.ReadBufferQueueDestroy(read_queue2); 127 } 128 129 TEST_F(DvrBufferQueueTest, GainBuffer) { 130 int ret = api_.WriteBufferQueueCreate( 131 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 132 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); 133 ASSERT_EQ(ret, 0); 134 135 DvrWriteBuffer* wb = nullptr; 136 EXPECT_FALSE(api_.WriteBufferIsValid(wb)); 137 138 DvrNativeBufferMetadata meta; 139 int fence_fd = -1; 140 ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta, 141 &fence_fd); 142 ASSERT_EQ(ret, 0); 143 EXPECT_EQ(fence_fd, -1); 144 EXPECT_NE(wb, nullptr); 145 EXPECT_TRUE(api_.WriteBufferIsValid(wb)); 146 } 147 148 TEST_F(DvrBufferQueueTest, AcquirePostGainRelease) { 149 int ret = api_.WriteBufferQueueCreate( 150 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 151 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); 152 ASSERT_EQ(ret, 0); 153 154 DvrReadBufferQueue* read_queue = nullptr; 155 DvrReadBuffer* rb = nullptr; 156 DvrWriteBuffer* wb = nullptr; 157 DvrNativeBufferMetadata meta1; 158 DvrNativeBufferMetadata meta2; 159 int fence_fd = -1; 160 161 ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue); 162 163 ASSERT_EQ(ret, 0); 164 ASSERT_NE(read_queue, nullptr); 165 166 api_.ReadBufferQueueSetBufferAvailableCallback( 167 read_queue, &BufferAvailableCallback, this); 168 169 // Gain buffer for writing. 170 ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, 171 &meta1, &fence_fd); 172 ASSERT_EQ(ret, 0); 173 ASSERT_NE(wb, nullptr); 174 ASSERT_TRUE(api_.WriteBufferIsValid(wb)); 175 ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d", 176 wb, fence_fd); 177 close(fence_fd); 178 179 // Post buffer to the read_queue. 180 meta1.timestamp = 42; 181 ret = api_.WriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1); 182 ASSERT_EQ(ret, 0); 183 ASSERT_FALSE(api_.WriteBufferIsValid(wb)); 184 wb = nullptr; 185 186 // Acquire buffer for reading. 187 ret = api_.ReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10, &rb, 188 &meta2, &fence_fd); 189 ASSERT_EQ(ret, 0); 190 ASSERT_NE(rb, nullptr); 191 192 // Dequeue is successfully, BufferAvailableCallback should be fired once. 193 ASSERT_EQ(buffer_available_count_, 1); 194 ASSERT_TRUE(api_.ReadBufferIsValid(rb)); 195 196 // Metadata should be passed along from producer to consumer properly. 197 ASSERT_EQ(meta1.timestamp, meta2.timestamp); 198 199 ALOGD_IF(TRACE, 200 "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb, 201 fence_fd); 202 close(fence_fd); 203 204 // Release buffer to the write_queue. 205 ret = api_.ReadBufferQueueReleaseBuffer(read_queue, rb, &meta2, 206 /*release_fence_fd=*/-1); 207 ASSERT_EQ(ret, 0); 208 ASSERT_FALSE(api_.ReadBufferIsValid(rb)); 209 rb = nullptr; 210 211 // TODO(b/34387835) Currently buffer allocation has to happen after all queues 212 // are initialized. 213 size_t capacity = api_.ReadBufferQueueGetCapacity(read_queue); 214 215 ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, capacity=%zu", capacity); 216 ASSERT_EQ(kQueueCapacity, capacity); 217 218 api_.ReadBufferQueueDestroy(read_queue); 219 } 220 221 TEST_F(DvrBufferQueueTest, GetANativeWindow) { 222 int ret = api_.WriteBufferQueueCreate( 223 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 224 /*capacity=*/0, /*user_metadata_size=*/0, &write_queue_); 225 ASSERT_EQ(0, ret); 226 ASSERT_NE(nullptr, write_queue_); 227 228 ANativeWindow* window = nullptr; 229 ret = api_.WriteBufferQueueGetANativeWindow(write_queue_, &window); 230 ASSERT_EQ(0, ret); 231 ASSERT_NE(nullptr, window); 232 233 uint32_t width = ANativeWindow_getWidth(window); 234 uint32_t height = ANativeWindow_getHeight(window); 235 uint32_t format = ANativeWindow_getFormat(window); 236 ASSERT_EQ(kBufferWidth, width); 237 ASSERT_EQ(kBufferHeight, height); 238 ASSERT_EQ(kBufferFormat, format); 239 } 240 241 // Create buffer queue of three buffers and dequeue three buffers out of it. 242 // Before each dequeue operation, we resize the buffer queue and expect the 243 // queue always return buffer with desired dimension. 244 TEST_F(DvrBufferQueueTest, ResizeBuffer) { 245 int ret = api_.WriteBufferQueueCreate( 246 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 247 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); 248 ASSERT_EQ(0, ret); 249 250 int fence_fd = -1; 251 252 DvrNativeBufferMetadata meta; 253 DvrReadBufferQueue* read_queue = nullptr; 254 DvrWriteBuffer* wb1 = nullptr; 255 DvrWriteBuffer* wb2 = nullptr; 256 DvrWriteBuffer* wb3 = nullptr; 257 AHardwareBuffer* ahb1 = nullptr; 258 AHardwareBuffer* ahb2 = nullptr; 259 AHardwareBuffer* ahb3 = nullptr; 260 AHardwareBuffer_Desc buffer_desc; 261 262 ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue); 263 264 ASSERT_EQ(0, ret); 265 ASSERT_NE(nullptr, read_queue); 266 267 api_.ReadBufferQueueSetBufferRemovedCallback(read_queue, 268 &BufferRemovedCallback, this); 269 270 // Handle all pending events on the read queue. 271 ret = api_.ReadBufferQueueHandleEvents(read_queue); 272 ASSERT_EQ(0, ret); 273 274 size_t capacity = api_.ReadBufferQueueGetCapacity(read_queue); 275 ALOGD_IF(TRACE, "TestResizeBuffer, capacity=%zu", capacity); 276 ASSERT_EQ(kQueueCapacity, capacity); 277 278 // Resize before dequeuing. 279 constexpr uint32_t w1 = 10; 280 ret = api_.WriteBufferQueueResizeBuffer(write_queue_, w1, kBufferHeight); 281 ASSERT_EQ(0, ret); 282 283 // Gain first buffer for writing. All buffers will be resized. 284 ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb1, 285 &meta, &fence_fd); 286 ASSERT_EQ(0, ret); 287 ASSERT_TRUE(api_.WriteBufferIsValid(wb1)); 288 ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p", wb1); 289 close(fence_fd); 290 291 // Check the buffer dimension. 292 ret = api_.WriteBufferGetAHardwareBuffer(wb1, &ahb1); 293 ASSERT_EQ(0, ret); 294 AHardwareBuffer_describe(ahb1, &buffer_desc); 295 ASSERT_EQ(w1, buffer_desc.width); 296 ASSERT_EQ(kBufferHeight, buffer_desc.height); 297 AHardwareBuffer_release(ahb1); 298 299 // For the first resize, all buffers are reallocated. 300 int expected_buffer_removed_count = kQueueCapacity; 301 ret = api_.ReadBufferQueueHandleEvents(read_queue); 302 ASSERT_EQ(0, ret); 303 ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_); 304 305 // Resize the queue. We are testing with blob format, keep height to be 1. 306 constexpr uint32_t w2 = 20; 307 ret = api_.WriteBufferQueueResizeBuffer(write_queue_, w2, kBufferHeight); 308 ASSERT_EQ(0, ret); 309 310 // The next buffer we dequeued should have new width. 311 ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb2, 312 &meta, &fence_fd); 313 ASSERT_EQ(0, ret); 314 ASSERT_TRUE(api_.WriteBufferIsValid(wb2)); 315 ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb2, 316 fence_fd); 317 close(fence_fd); 318 319 // Check the buffer dimension, should be new width 320 ret = api_.WriteBufferGetAHardwareBuffer(wb2, &ahb2); 321 ASSERT_EQ(0, ret); 322 AHardwareBuffer_describe(ahb2, &buffer_desc); 323 ASSERT_EQ(w2, buffer_desc.width); 324 AHardwareBuffer_release(ahb2); 325 326 // For the second resize, all but one buffers are reallocated. 327 expected_buffer_removed_count += (kQueueCapacity - 1); 328 ret = api_.ReadBufferQueueHandleEvents(read_queue); 329 ASSERT_EQ(0, ret); 330 ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_); 331 332 // Resize the queue for the third time. 333 constexpr uint32_t w3 = 30; 334 ret = api_.WriteBufferQueueResizeBuffer(write_queue_, w3, kBufferHeight); 335 ASSERT_EQ(0, ret); 336 337 // The next buffer we dequeued should have new width. 338 ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb3, 339 &meta, &fence_fd); 340 ASSERT_EQ(0, ret); 341 ASSERT_TRUE(api_.WriteBufferIsValid(wb3)); 342 ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb3, 343 fence_fd); 344 close(fence_fd); 345 346 // Check the buffer dimension, should be new width 347 ret = api_.WriteBufferGetAHardwareBuffer(wb3, &ahb3); 348 ASSERT_EQ(0, ret); 349 AHardwareBuffer_describe(ahb3, &buffer_desc); 350 ASSERT_EQ(w3, buffer_desc.width); 351 AHardwareBuffer_release(ahb3); 352 353 // For the third resize, all but two buffers are reallocated. 354 expected_buffer_removed_count += (kQueueCapacity - 2); 355 ret = api_.ReadBufferQueueHandleEvents(read_queue); 356 ASSERT_EQ(0, ret); 357 ASSERT_EQ(expected_buffer_removed_count, buffer_removed_count_); 358 359 api_.ReadBufferQueueDestroy(read_queue); 360 } 361 362 TEST_F(DvrBufferQueueTest, ReadQueueEventFd) { 363 int ret = api_.WriteBufferQueueCreate( 364 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 365 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); 366 ASSERT_EQ(0, ret); 367 368 DvrReadBufferQueue* read_queue = nullptr; 369 ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue); 370 371 ASSERT_EQ(0, ret); 372 ASSERT_NE(nullptr, read_queue); 373 374 int event_fd = api_.ReadBufferQueueGetEventFd(read_queue); 375 ASSERT_GT(event_fd, 0); 376 } 377 378 // Verifies a Dvr{Read,Write}BufferQueue contains the same set of 379 // Dvr{Read,Write}Buffer(s) during their lifecycles. And for the same buffer_id, 380 // the corresponding AHardwareBuffer handle stays the same. 381 TEST_F(DvrBufferQueueTest, StableBufferIdAndHardwareBuffer) { 382 int ret = api_.WriteBufferQueueCreate( 383 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 384 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); 385 ASSERT_EQ(0, ret); 386 387 int fence_fd = -1; 388 DvrReadBufferQueue* read_queue = nullptr; 389 EXPECT_EQ(0, api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue)); 390 391 // Read buffers. 392 std::array<DvrReadBuffer*, kQueueCapacity> rbs; 393 // Write buffers. 394 std::array<DvrWriteBuffer*, kQueueCapacity> wbs; 395 // Buffer metadata. 396 std::array<DvrNativeBufferMetadata, kQueueCapacity> metas; 397 // Hardware buffers for Read buffers. 398 std::unordered_map<int, AHardwareBuffer*> rhbs; 399 // Hardware buffers for Write buffers. 400 std::unordered_map<int, AHardwareBuffer*> whbs; 401 402 constexpr int kNumTests = 100; 403 404 // This test runs the following operations many many times. Thus we prefer to 405 // use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output. 406 std::function<void(size_t i)> Gain = [&](size_t i) { 407 int ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/10, 408 &wbs[i], &metas[i], &fence_fd); 409 ASSERT_EQ(ret, 0); 410 ASSERT_LT(fence_fd, 0); // expect invalid fence. 411 ASSERT_TRUE(api_.WriteBufferIsValid(wbs[i])); 412 int buffer_id = api_.WriteBufferGetId(wbs[i]); 413 ASSERT_GT(buffer_id, 0); 414 415 AHardwareBuffer* hb = nullptr; 416 ASSERT_EQ(0, api_.WriteBufferGetAHardwareBuffer(wbs[i], &hb)); 417 418 auto whb_it = whbs.find(buffer_id); 419 if (whb_it == whbs.end()) { 420 // If this is a new buffer id, check that total number of unique 421 // hardware buffers won't exceed queue capacity. 422 ASSERT_LT(whbs.size(), kQueueCapacity); 423 whbs.emplace(buffer_id, hb); 424 } else { 425 // If this is a buffer id we have seen before, check that the 426 // buffer_id maps to the same AHardwareBuffer handle. 427 ASSERT_EQ(hb, whb_it->second); 428 } 429 }; 430 431 std::function<void(size_t i)> Post = [&](size_t i) { 432 ASSERT_TRUE(api_.WriteBufferIsValid(wbs[i])); 433 434 metas[i].timestamp++; 435 int ret = api_.WriteBufferQueuePostBuffer(write_queue_, wbs[i], &metas[i], 436 /*fence=*/-1); 437 ASSERT_EQ(ret, 0); 438 }; 439 440 std::function<void(size_t i)> Acquire = [&](size_t i) { 441 int ret = api_.ReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10, 442 &rbs[i], &metas[i], &fence_fd); 443 ASSERT_EQ(ret, 0); 444 ASSERT_LT(fence_fd, 0); // expect invalid fence. 445 ASSERT_TRUE(api_.ReadBufferIsValid(rbs[i])); 446 447 int buffer_id = api_.ReadBufferGetId(rbs[i]); 448 ASSERT_GT(buffer_id, 0); 449 450 AHardwareBuffer* hb = nullptr; 451 ASSERT_EQ(0, api_.ReadBufferGetAHardwareBuffer(rbs[i], &hb)); 452 453 auto rhb_it = rhbs.find(buffer_id); 454 if (rhb_it == rhbs.end()) { 455 // If this is a new buffer id, check that total number of unique hardware 456 // buffers won't exceed queue capacity. 457 ASSERT_LT(rhbs.size(), kQueueCapacity); 458 rhbs.emplace(buffer_id, hb); 459 } else { 460 // If this is a buffer id we have seen before, check that the buffer_id 461 // maps to the same AHardwareBuffer handle. 462 ASSERT_EQ(hb, rhb_it->second); 463 } 464 }; 465 466 std::function<void(size_t i)> Release = [&](size_t i) { 467 ASSERT_TRUE(api_.ReadBufferIsValid(rbs[i])); 468 469 int ret = api_.ReadBufferQueueReleaseBuffer(read_queue, rbs[i], &metas[i], 470 /*release_fence_fd=*/-1); 471 ASSERT_EQ(ret, 0); 472 }; 473 474 // Scenario one: 475 for (int i = 0; i < kNumTests; i++) { 476 // Gain all write buffers. 477 for (size_t i = 0; i < kQueueCapacity; i++) { 478 ASSERT_NO_FATAL_FAILURE(Gain(i)); 479 } 480 // Post all write buffers. 481 for (size_t i = 0; i < kQueueCapacity; i++) { 482 ASSERT_NO_FATAL_FAILURE(Post(i)); 483 } 484 // Acquire all read buffers. 485 for (size_t i = 0; i < kQueueCapacity; i++) { 486 ASSERT_NO_FATAL_FAILURE(Acquire(i)); 487 } 488 // Release all read buffers. 489 for (size_t i = 0; i < kQueueCapacity; i++) { 490 ASSERT_NO_FATAL_FAILURE(Release(i)); 491 } 492 } 493 494 // Scenario two: 495 for (int i = 0; i < kNumTests; i++) { 496 // Gain and post all write buffers. 497 for (size_t i = 0; i < kQueueCapacity; i++) { 498 ASSERT_NO_FATAL_FAILURE(Gain(i)); 499 ASSERT_NO_FATAL_FAILURE(Post(i)); 500 } 501 // Acquire and release all read buffers. 502 for (size_t i = 0; i < kQueueCapacity; i++) { 503 ASSERT_NO_FATAL_FAILURE(Acquire(i)); 504 ASSERT_NO_FATAL_FAILURE(Release(i)); 505 } 506 } 507 508 // Scenario three: 509 for (int i = 0; i < kNumTests; i++) { 510 // Gain all write buffers then post them in reversed order. 511 for (size_t i = 0; i < kQueueCapacity; i++) { 512 ASSERT_NO_FATAL_FAILURE(Gain(i)); 513 } 514 for (size_t i = 0; i < kQueueCapacity; i++) { 515 ASSERT_NO_FATAL_FAILURE(Post(kQueueCapacity - 1 - i)); 516 } 517 518 // Acquire all write buffers then release them in reversed order. 519 for (size_t i = 0; i < kQueueCapacity; i++) { 520 ASSERT_NO_FATAL_FAILURE(Acquire(i)); 521 } 522 for (size_t i = 0; i < kQueueCapacity; i++) { 523 ASSERT_NO_FATAL_FAILURE(Release(kQueueCapacity - 1 - i)); 524 } 525 } 526 } 527 528 TEST_F(DvrBufferQueueTest, ConsumerReleaseAfterProducerDestroy) { 529 int ret = api_.WriteBufferQueueCreate( 530 kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, 531 kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); 532 ASSERT_EQ(ret, 0); 533 534 DvrReadBufferQueue* read_queue = nullptr; 535 DvrReadBuffer* rb = nullptr; 536 DvrWriteBuffer* wb = nullptr; 537 DvrNativeBufferMetadata meta1; 538 DvrNativeBufferMetadata meta2; 539 int fence_fd = -1; 540 541 ret = api_.WriteBufferQueueCreateReadQueue(write_queue_, &read_queue); 542 ASSERT_EQ(ret, 0); 543 544 api_.ReadBufferQueueSetBufferAvailableCallback( 545 read_queue, &BufferAvailableCallback, this); 546 547 // Gain buffer for writing. 548 ret = api_.WriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, 549 &meta1, &fence_fd); 550 ASSERT_EQ(ret, 0); 551 close(fence_fd); 552 553 // Post buffer to the read_queue. 554 ret = api_.WriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1); 555 ASSERT_EQ(ret, 0); 556 wb = nullptr; 557 558 // Acquire buffer for reading. 559 ret = api_.ReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/10, &rb, 560 &meta2, &fence_fd); 561 ASSERT_EQ(ret, 0); 562 close(fence_fd); 563 564 // Destroy the write buffer queue and make sure the reader queue is picking 565 // these events up. 566 api_.WriteBufferQueueDestroy(write_queue_); 567 ret = api_.ReadBufferQueueHandleEvents(read_queue); 568 ASSERT_EQ(0, ret); 569 570 // Release buffer to the write_queue. 571 ret = api_.ReadBufferQueueReleaseBuffer(read_queue, rb, &meta2, 572 /*release_fence_fd=*/-1); 573 ASSERT_EQ(ret, 0); 574 rb = nullptr; 575 576 api_.ReadBufferQueueDestroy(read_queue); 577 } 578 579 } // namespace 580