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