1 #include "include/dvr/dvr_api.h" 2 #include "include/dvr/dvr_buffer_queue.h" 3 4 #include <android/native_window.h> 5 #include <private/dvr/buffer_hub_queue_producer.h> 6 7 #include "dvr_internal.h" 8 #include "dvr_buffer_queue_internal.h" 9 10 using namespace android; 11 using android::dvr::BufferConsumer; 12 using android::dvr::BufferHubBuffer; 13 using android::dvr::BufferHubQueueProducer; 14 using android::dvr::BufferProducer; 15 using android::dvr::ConsumerQueue; 16 using android::dvr::ProducerQueue; 17 using android::dvr::ProducerQueueConfigBuilder; 18 using android::dvr::UsagePolicy; 19 20 extern "C" { 21 22 DvrWriteBufferQueue::DvrWriteBufferQueue( 23 const std::shared_ptr<ProducerQueue>& producer_queue) 24 : producer_queue_(producer_queue), 25 width_(producer_queue->default_width()), 26 height_(producer_queue->default_height()), 27 format_(producer_queue->default_format()) {} 28 29 int DvrWriteBufferQueue::GetNativeWindow(ANativeWindow** out_window) { 30 if (native_window_ == nullptr) { 31 // Lazy creation of |native_window|, as not everyone is using 32 // DvrWriteBufferQueue as an external surface. 33 sp<IGraphicBufferProducer> gbp = 34 BufferHubQueueProducer::Create(producer_queue_); 35 native_window_ = new Surface(gbp, true); 36 } 37 38 *out_window = static_cast<ANativeWindow*>(native_window_.get()); 39 return 0; 40 } 41 42 int DvrWriteBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) { 43 std::unique_ptr<ConsumerQueue> consumer_queue = 44 producer_queue_->CreateConsumerQueue(); 45 if (consumer_queue == nullptr) { 46 ALOGE( 47 "DvrWriteBufferQueue::CreateReadQueue: Failed to create consumer queue " 48 "from producer queue: queue_id=%d.", producer_queue_->id()); 49 return -ENOMEM; 50 } 51 52 *out_read_queue = new DvrReadBufferQueue(std::move(consumer_queue)); 53 return 0; 54 } 55 56 int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer, 57 int* out_fence_fd) { 58 DvrNativeBufferMetadata meta; 59 DvrWriteBuffer* buffer = nullptr; 60 int fence_fd = -1; 61 if (const int ret = GainBuffer(timeout, &buffer, &meta, &fence_fd)) 62 return ret; 63 if (!buffer) 64 return -ENOMEM; 65 66 write_buffers_[buffer->slot].reset(buffer); 67 write_buffer->write_buffer = std::move(buffer->write_buffer); 68 *out_fence_fd = fence_fd; 69 return 0; 70 } 71 72 int DvrWriteBufferQueue::GainBuffer(int timeout, 73 DvrWriteBuffer** out_write_buffer, 74 DvrNativeBufferMetadata* out_meta, 75 int* out_fence_fd) { 76 size_t slot; 77 pdx::LocalHandle release_fence; 78 79 // Need to retry N+1 times, where N is total number of buffers in the queue. 80 // As in the worst case, we will dequeue all N buffers and reallocate them, on 81 // the {N+1}th dequeue, we are guaranteed to get a buffer with new dimension. 82 size_t max_retries = 1 + producer_queue_->capacity(); 83 size_t retry = 0; 84 85 for (; retry < max_retries; retry++) { 86 auto buffer_status = 87 producer_queue_->Dequeue(timeout, &slot, out_meta, &release_fence); 88 if (!buffer_status) { 89 ALOGE_IF(buffer_status.error() != ETIMEDOUT, 90 "DvrWriteBufferQueue::GainBuffer: Failed to dequeue buffer: %s", 91 buffer_status.GetErrorMessage().c_str()); 92 return -buffer_status.error(); 93 } 94 95 if (write_buffers_[slot] == nullptr) { 96 // Lazy initialization of a write_buffers_ slot. Note that a slot will 97 // only be dynamically allocated once during the entire cycle life of a 98 // queue. 99 write_buffers_[slot] = std::make_unique<DvrWriteBuffer>(); 100 write_buffers_[slot]->slot = slot; 101 } 102 103 LOG_ALWAYS_FATAL_IF( 104 write_buffers_[slot]->write_buffer, 105 "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot); 106 write_buffers_[slot]->write_buffer = std::move(buffer_status.take()); 107 108 const auto& buffer_producer = write_buffers_[slot]->write_buffer; 109 if (!buffer_producer) 110 return -ENOMEM; 111 112 if (width_ == buffer_producer->width() && 113 height_ == buffer_producer->height() && 114 format_ == buffer_producer->format()) { 115 // Producer queue returns a buffer matches the current request. 116 break; 117 } 118 119 // Needs reallocation. Note that if there are already multiple available 120 // buffers in the queue, the next one returned from |queue_->Dequeue| may 121 // still have the old buffer dimension or format. Retry up to N+1 times or 122 // until we dequeued a buffer with new configuration. 123 ALOGD_IF(TRACE, 124 "DvrWriteBufferQueue::Dequeue: requested buffer at slot: %zu " 125 "(w=%u, h=%u, fmt=%u) is different from the buffer returned " 126 "(w=%u, h=%u, fmt=%u). Need re-allocation.", 127 slot, width_, height_, format_, buffer_producer->width(), 128 buffer_producer->height(), buffer_producer->format()); 129 130 // Currently, we are not storing |layer_count| and |usage| in queue 131 // configuration. Copy those setup from the last buffer dequeued before we 132 // remove it. 133 uint32_t old_layer_count = buffer_producer->layer_count(); 134 uint64_t old_usage = buffer_producer->usage(); 135 136 // Allocate a new producer buffer with new buffer configs. Note that if 137 // there are already multiple available buffers in the queue, the next one 138 // returned from |queue_->Dequeue| may still have the old buffer dimension 139 // or format. Retry up to BufferHubQueue::kMaxQueueCapacity times or until 140 // we dequeued a buffer with new configuration. 141 auto remove_status = producer_queue_->RemoveBuffer(slot); 142 if (!remove_status) { 143 ALOGE("DvrWriteBufferQueue::Dequeue: Failed to remove buffer: %s", 144 remove_status.GetErrorMessage().c_str()); 145 return -remove_status.error(); 146 } 147 // Make sure that the previously allocated buffer is dereferenced from 148 // write_buffers_ array. 149 write_buffers_[slot]->write_buffer = nullptr; 150 151 auto allocate_status = producer_queue_->AllocateBuffer( 152 width_, height_, old_layer_count, format_, old_usage); 153 if (!allocate_status) { 154 ALOGE("DvrWriteBufferQueue::Dequeue: Failed to allocate buffer: %s", 155 allocate_status.GetErrorMessage().c_str()); 156 return -allocate_status.error(); 157 } 158 } 159 160 if (retry >= max_retries) { 161 ALOGE( 162 "DvrWriteBufferQueue::Dequeue: Failed to re-allocate buffer after " 163 "resizing."); 164 return -ENOMEM; 165 } 166 167 *out_write_buffer = write_buffers_[slot].release(); 168 *out_fence_fd = release_fence.Release(); 169 170 return 0; 171 } 172 173 int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer, 174 const DvrNativeBufferMetadata* meta, 175 int ready_fence_fd) { 176 LOG_FATAL_IF( 177 (write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()), 178 "DvrWriteBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot); 179 180 // Some basic sanity checks before we put the buffer back into a slot. 181 size_t slot = static_cast<size_t>(write_buffer->slot); 182 if (write_buffers_[slot] != nullptr) { 183 ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot); 184 return -EINVAL; 185 } 186 if (write_buffer->write_buffer == nullptr) { 187 ALOGE("DvrWriteBufferQueue::PostBuffer: Invalid write buffer."); 188 return -EINVAL; 189 } 190 if (write_buffer->write_buffer->id() != producer_queue_->GetBufferId(slot)) { 191 ALOGE( 192 "DvrWriteBufferQueue::PostBuffer: Buffer to be posted does not " 193 "belong to this buffer queue. Posting buffer: id=%d, buffer in " 194 "queue: id=%d", 195 write_buffer->write_buffer->id(), producer_queue_->GetBufferId(slot)); 196 return -EINVAL; 197 } 198 199 write_buffer->write_buffer->SetQueueIndex(next_post_index_++); 200 pdx::LocalHandle fence(ready_fence_fd); 201 const int ret = write_buffer->write_buffer->PostAsync(meta, fence); 202 if (ret < 0) { 203 ALOGE("DvrWriteBufferQueue::PostBuffer: Failed to post buffer, ret=%d", 204 ret); 205 return ret; 206 } 207 208 // Put the DvrWriteBuffer pointer back into its slot for reuse. 209 write_buffers_[slot].reset(write_buffer); 210 // It's import to reset the write buffer client now. It should stay invalid 211 // until next GainBuffer on the same slot. 212 write_buffers_[slot]->write_buffer = nullptr; 213 return 0; 214 } 215 216 int DvrWriteBufferQueue::ResizeBuffer(uint32_t width, uint32_t height) { 217 if (width == 0 || height == 0) { 218 ALOGE( 219 "DvrWriteBufferQueue::ResizeBuffer: invalid buffer dimension: w=%u, " 220 "h=%u.", 221 width, height); 222 return -EINVAL; 223 } 224 225 width_ = width; 226 height_ = height; 227 return 0; 228 } 229 230 int dvrWriteBufferQueueCreate(uint32_t width, uint32_t height, uint32_t format, 231 uint32_t layer_count, uint64_t usage, 232 size_t capacity, size_t metadata_size, 233 DvrWriteBufferQueue** out_write_queue) { 234 if (!out_write_queue) 235 return -EINVAL; 236 237 auto config_builder = ProducerQueueConfigBuilder() 238 .SetDefaultWidth(width) 239 .SetDefaultHeight(height) 240 .SetDefaultFormat(format) 241 .SetMetadataSize(metadata_size); 242 std::unique_ptr<ProducerQueue> producer_queue = 243 ProducerQueue::Create(config_builder.Build(), UsagePolicy{}); 244 if (!producer_queue) { 245 ALOGE("dvrWriteBufferQueueCreate: Failed to create producer queue."); 246 return -ENOMEM; 247 } 248 249 auto status = producer_queue->AllocateBuffers(width, height, layer_count, 250 format, usage, capacity); 251 if (!status.ok()) { 252 ALOGE("dvrWriteBufferQueueCreate: Failed to allocate buffers."); 253 return -ENOMEM; 254 } 255 256 *out_write_queue = new DvrWriteBufferQueue(std::move(producer_queue)); 257 return 0; 258 } 259 260 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) { 261 delete write_queue; 262 } 263 264 ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) { 265 if (!write_queue) 266 return -EINVAL; 267 268 return write_queue->capacity(); 269 } 270 271 int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) { 272 if (!write_queue) 273 return -EINVAL; 274 275 return write_queue->id(); 276 } 277 278 int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue, 279 ANativeWindow** out_window) { 280 ALOGW( 281 "dvrWriteBufferQueueGetExternalSurface: This API has been deprecated and " 282 "renamed to dvrWriteBufferQueueGetANativeWindow."); 283 return dvrWriteBufferQueueGetANativeWindow(write_queue, out_window); 284 } 285 286 int dvrWriteBufferQueueGetANativeWindow(DvrWriteBufferQueue* write_queue, 287 ANativeWindow** out_window) { 288 if (!write_queue || !out_window) 289 return -EINVAL; 290 291 return write_queue->GetNativeWindow(out_window); 292 } 293 294 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue, 295 DvrReadBufferQueue** out_read_queue) { 296 if (!write_queue || !out_read_queue) 297 return -EINVAL; 298 299 return write_queue->CreateReadQueue(out_read_queue); 300 } 301 302 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout, 303 DvrWriteBuffer* write_buffer, 304 int* out_fence_fd) { 305 if (!write_queue || !write_buffer || !out_fence_fd) 306 return -EINVAL; 307 308 return write_queue->Dequeue(timeout, write_buffer, out_fence_fd); 309 } 310 311 int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout, 312 DvrWriteBuffer** out_write_buffer, 313 DvrNativeBufferMetadata* out_meta, 314 int* out_fence_fd) { 315 if (!write_queue || !out_write_buffer || !out_meta || !out_fence_fd) 316 return -EINVAL; 317 318 return write_queue->GainBuffer(timeout, out_write_buffer, out_meta, 319 out_fence_fd); 320 } 321 322 int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue, 323 DvrWriteBuffer* write_buffer, 324 const DvrNativeBufferMetadata* meta, 325 int ready_fence_fd) { 326 if (!write_queue || !write_buffer || !write_buffer->write_buffer || !meta) 327 return -EINVAL; 328 329 return write_queue->PostBuffer(write_buffer, meta, ready_fence_fd); 330 } 331 332 int dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue* write_queue, 333 uint32_t width, uint32_t height) { 334 if (!write_queue) 335 return -EINVAL; 336 337 return write_queue->ResizeBuffer(width, height); 338 } 339 340 // ReadBufferQueue 341 342 DvrReadBufferQueue::DvrReadBufferQueue( 343 const std::shared_ptr<ConsumerQueue>& consumer_queue) 344 : consumer_queue_(consumer_queue) {} 345 346 int DvrReadBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) { 347 std::unique_ptr<ConsumerQueue> consumer_queue = 348 consumer_queue_->CreateConsumerQueue(); 349 if (consumer_queue == nullptr) { 350 ALOGE( 351 "DvrReadBufferQueue::CreateReadQueue: Failed to create consumer queue " 352 "from producer queue: queue_id=%d.", consumer_queue_->id()); 353 return -ENOMEM; 354 } 355 356 *out_read_queue = new DvrReadBufferQueue(std::move(consumer_queue)); 357 return 0; 358 } 359 360 int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer, 361 int* out_fence_fd, void* out_meta, 362 size_t meta_size_bytes) { 363 if (meta_size_bytes != consumer_queue_->metadata_size()) { 364 ALOGE( 365 "DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), " 366 "but actual (%zu).", 367 consumer_queue_->metadata_size(), meta_size_bytes); 368 return -EINVAL; 369 } 370 371 size_t slot; 372 pdx::LocalHandle acquire_fence; 373 auto buffer_status = consumer_queue_->Dequeue( 374 timeout, &slot, out_meta, meta_size_bytes, &acquire_fence); 375 if (!buffer_status) { 376 ALOGE_IF(buffer_status.error() != ETIMEDOUT, 377 "dvrReadBufferQueueDequeue: Failed to dequeue buffer: %s", 378 buffer_status.GetErrorMessage().c_str()); 379 return -buffer_status.error(); 380 } 381 382 read_buffer->read_buffer = buffer_status.take(); 383 *out_fence_fd = acquire_fence.Release(); 384 385 return 0; 386 } 387 388 int DvrReadBufferQueue::AcquireBuffer(int timeout, 389 DvrReadBuffer** out_read_buffer, 390 DvrNativeBufferMetadata* out_meta, 391 int* out_fence_fd) { 392 size_t slot; 393 pdx::LocalHandle acquire_fence; 394 auto buffer_status = 395 consumer_queue_->Dequeue(timeout, &slot, out_meta, &acquire_fence); 396 if (!buffer_status) { 397 ALOGE_IF(buffer_status.error() != ETIMEDOUT, 398 "DvrReadBufferQueue::AcquireBuffer: Failed to dequeue buffer: %s", 399 buffer_status.GetErrorMessage().c_str()); 400 return -buffer_status.error(); 401 } 402 403 if (read_buffers_[slot] == nullptr) { 404 // Lazy initialization of a read_buffers_ slot. Note that a slot will only 405 // be dynamically allocated once during the entire cycle life of a queue. 406 read_buffers_[slot] = std::make_unique<DvrReadBuffer>(); 407 read_buffers_[slot]->slot = slot; 408 } 409 410 LOG_FATAL_IF( 411 read_buffers_[slot]->read_buffer, 412 "DvrReadBufferQueue::AcquireBuffer: Buffer slot is not empty: %zu", slot); 413 read_buffers_[slot]->read_buffer = std::move(buffer_status.take()); 414 415 *out_read_buffer = read_buffers_[slot].release(); 416 *out_fence_fd = acquire_fence.Release(); 417 418 return 0; 419 } 420 421 int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer, 422 const DvrNativeBufferMetadata* meta, 423 int release_fence_fd) { 424 LOG_FATAL_IF( 425 (read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()), 426 "DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot); 427 428 // Some basic sanity checks before we put the buffer back into a slot. 429 size_t slot = static_cast<size_t>(read_buffer->slot); 430 if (read_buffers_[slot] != nullptr) { 431 ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot); 432 return -EINVAL; 433 } 434 if (read_buffer->read_buffer == nullptr) { 435 ALOGE("DvrReadBufferQueue::ReleaseBuffer: Invalid read buffer."); 436 return -EINVAL; 437 } 438 if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) { 439 ALOGE( 440 "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not " 441 "belong to this buffer queue. Releasing buffer: id=%d, buffer in " 442 "queue: id=%d", 443 read_buffer->read_buffer->id(), consumer_queue_->GetBufferId(slot)); 444 return -EINVAL; 445 } 446 447 pdx::LocalHandle fence(release_fence_fd); 448 int ret = read_buffer->read_buffer->ReleaseAsync(meta, fence); 449 if (ret < 0) { 450 ALOGE("DvrReadBufferQueue::ReleaseBuffer: Failed to release buffer, ret=%d", 451 ret); 452 return ret; 453 } 454 455 // Put the DvrReadBuffer pointer back into its slot for reuse. 456 read_buffers_[slot].reset(read_buffer); 457 // It's import to reset the read buffer client now. It should stay invalid 458 // until next AcquireBuffer on the same slot. 459 read_buffers_[slot]->read_buffer = nullptr; 460 return 0; 461 } 462 463 void DvrReadBufferQueue::SetBufferAvailableCallback( 464 DvrReadBufferQueueBufferAvailableCallback callback, void* context) { 465 if (callback == nullptr) { 466 consumer_queue_->SetBufferAvailableCallback(nullptr); 467 } else { 468 consumer_queue_->SetBufferAvailableCallback( 469 [callback, context]() { callback(context); }); 470 } 471 } 472 473 void DvrReadBufferQueue::SetBufferRemovedCallback( 474 DvrReadBufferQueueBufferRemovedCallback callback, void* context) { 475 if (callback == nullptr) { 476 consumer_queue_->SetBufferRemovedCallback(nullptr); 477 } else { 478 consumer_queue_->SetBufferRemovedCallback( 479 [callback, context](const std::shared_ptr<BufferHubBuffer>& buffer) { 480 // When buffer is removed from the queue, the slot is already invalid. 481 auto read_buffer = std::make_unique<DvrReadBuffer>(); 482 read_buffer->read_buffer = 483 std::static_pointer_cast<BufferConsumer>(buffer); 484 callback(read_buffer.release(), context); 485 }); 486 } 487 } 488 489 int DvrReadBufferQueue::HandleEvents() { 490 // TODO(jwcai) Probably should change HandleQueueEvents to return Status. 491 consumer_queue_->HandleQueueEvents(); 492 return 0; 493 } 494 495 void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) { 496 delete read_queue; 497 } 498 499 ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) { 500 if (!read_queue) 501 return -EINVAL; 502 503 return read_queue->capacity(); 504 } 505 506 int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) { 507 if (!read_queue) 508 return -EINVAL; 509 510 return read_queue->id(); 511 } 512 513 int dvrReadBufferQueueGetEventFd(DvrReadBufferQueue* read_queue) { 514 if (!read_queue) 515 return -EINVAL; 516 517 return read_queue->event_fd(); 518 } 519 520 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue, 521 DvrReadBufferQueue** out_read_queue) { 522 if (!read_queue || !out_read_queue) 523 return -EINVAL; 524 525 return read_queue->CreateReadQueue(out_read_queue); 526 } 527 528 int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout, 529 DvrReadBuffer* read_buffer, int* out_fence_fd, 530 void* out_meta, size_t meta_size_bytes) { 531 if (!read_queue || !read_buffer || !out_fence_fd) 532 return -EINVAL; 533 534 if (meta_size_bytes != 0 && !out_meta) 535 return -EINVAL; 536 537 return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, out_meta, 538 meta_size_bytes); 539 } 540 541 int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout, 542 DvrReadBuffer** out_read_buffer, 543 DvrNativeBufferMetadata* out_meta, 544 int* out_fence_fd) { 545 if (!read_queue || !out_read_buffer || !out_meta || !out_fence_fd) 546 return -EINVAL; 547 548 return read_queue->AcquireBuffer(timeout, out_read_buffer, out_meta, 549 out_fence_fd); 550 } 551 552 int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue, 553 DvrReadBuffer* read_buffer, 554 const DvrNativeBufferMetadata* meta, 555 int release_fence_fd) { 556 if (!read_queue || !read_buffer || !read_buffer->read_buffer || !meta) 557 return -EINVAL; 558 559 return read_queue->ReleaseBuffer(read_buffer, meta, release_fence_fd); 560 } 561 562 int dvrReadBufferQueueSetBufferAvailableCallback( 563 DvrReadBufferQueue* read_queue, 564 DvrReadBufferQueueBufferAvailableCallback callback, void* context) { 565 if (!read_queue) 566 return -EINVAL; 567 568 read_queue->SetBufferAvailableCallback(callback, context); 569 return 0; 570 } 571 572 int dvrReadBufferQueueSetBufferRemovedCallback( 573 DvrReadBufferQueue* read_queue, 574 DvrReadBufferQueueBufferRemovedCallback callback, void* context) { 575 if (!read_queue) 576 return -EINVAL; 577 578 read_queue->SetBufferRemovedCallback(callback, context); 579 return 0; 580 } 581 582 int dvrReadBufferQueueHandleEvents(DvrReadBufferQueue* read_queue) { 583 if (!read_queue) 584 return -EINVAL; 585 586 return read_queue->HandleEvents(); 587 } 588 589 } // extern "C" 590