Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | //#define LOG_NDEBUG 0 |
| 18 | #define LOG_TAG "Codec2-OutputBufferQueue" |
Arun Johnson | 7ba6707 | 2023-11-06 22:23:04 +0000 | [diff] [blame] | 19 | #define ATRACE_TAG ATRACE_TAG_VIDEO |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 20 | #include <android-base/logging.h> |
Arun Johnson | 7ba6707 | 2023-11-06 22:23:04 +0000 | [diff] [blame] | 21 | #include <utils/Trace.h> |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 22 | |
| 23 | #include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h> |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 24 | #include <codec2/hidl/output.h> |
| 25 | #include <cutils/ashmem.h> |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 26 | #include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h> |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 27 | #include <sys/mman.h> |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 28 | |
| 29 | #include <C2AllocatorGralloc.h> |
| 30 | #include <C2BlockInternal.h> |
| 31 | #include <C2Buffer.h> |
| 32 | #include <C2PlatformSupport.h> |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 33 | #include <C2SurfaceSyncObj.h> |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 34 | |
| 35 | #include <iomanip> |
| 36 | |
| 37 | namespace android { |
| 38 | namespace hardware { |
| 39 | namespace media { |
| 40 | namespace c2 { |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 41 | |
| 42 | using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue:: |
| 43 | V2_0::IGraphicBufferProducer; |
| 44 | using B2HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue:: |
| 45 | V2_0::utils::B2HGraphicBufferProducer; |
| 46 | |
| 47 | namespace /* unnamed */ { |
| 48 | |
| 49 | // Create a GraphicBuffer object from a graphic block. |
| 50 | sp<GraphicBuffer> createGraphicBuffer(const C2ConstGraphicBlock& block) { |
| 51 | uint32_t width; |
| 52 | uint32_t height; |
| 53 | uint32_t format; |
| 54 | uint64_t usage; |
| 55 | uint32_t stride; |
| 56 | uint32_t generation; |
| 57 | uint64_t bqId; |
| 58 | int32_t bqSlot; |
| 59 | _UnwrapNativeCodec2GrallocMetadata( |
| 60 | block.handle(), &width, &height, &format, &usage, |
| 61 | &stride, &generation, &bqId, reinterpret_cast<uint32_t*>(&bqSlot)); |
| 62 | native_handle_t *grallocHandle = |
| 63 | UnwrapNativeCodec2GrallocHandle(block.handle()); |
| 64 | sp<GraphicBuffer> graphicBuffer = |
| 65 | new GraphicBuffer(grallocHandle, |
| 66 | GraphicBuffer::CLONE_HANDLE, |
| 67 | width, height, format, |
| 68 | 1, usage, stride); |
| 69 | native_handle_delete(grallocHandle); |
| 70 | return graphicBuffer; |
| 71 | } |
| 72 | |
| 73 | template <typename BlockProcessor> |
| 74 | void forEachBlock(C2FrameData& frameData, |
| 75 | BlockProcessor process) { |
| 76 | for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) { |
| 77 | if (buffer) { |
| 78 | for (const C2ConstGraphicBlock& block : |
| 79 | buffer->data().graphicBlocks()) { |
| 80 | process(block); |
| 81 | } |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | template <typename BlockProcessor> |
| 87 | void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList, |
| 88 | BlockProcessor process) { |
| 89 | for (const std::unique_ptr<C2Work>& work : workList) { |
| 90 | if (!work) { |
| 91 | continue; |
| 92 | } |
| 93 | for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) { |
| 94 | if (worklet) { |
| 95 | forEachBlock(worklet->output, process); |
| 96 | } |
| 97 | } |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | sp<HGraphicBufferProducer> getHgbp(const sp<IGraphicBufferProducer>& igbp) { |
| 102 | sp<HGraphicBufferProducer> hgbp = |
| 103 | igbp->getHalInterface<HGraphicBufferProducer>(); |
| 104 | return hgbp ? hgbp : |
| 105 | new B2HGraphicBufferProducer(igbp); |
| 106 | } |
| 107 | |
| 108 | status_t attachToBufferQueue(const C2ConstGraphicBlock& block, |
| 109 | const sp<IGraphicBufferProducer>& igbp, |
| 110 | uint32_t generation, |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 111 | int32_t* bqSlot, |
| 112 | std::shared_ptr<C2SurfaceSyncMemory> syncMem) { |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 113 | if (!igbp) { |
| 114 | LOG(WARNING) << "attachToBufferQueue -- null producer."; |
| 115 | return NO_INIT; |
| 116 | } |
| 117 | |
| 118 | sp<GraphicBuffer> graphicBuffer = createGraphicBuffer(block); |
| 119 | graphicBuffer->setGenerationNumber(generation); |
| 120 | |
| 121 | LOG(VERBOSE) << "attachToBufferQueue -- attaching buffer:" |
| 122 | << " block dimension " << block.width() << "x" |
| 123 | << block.height() |
| 124 | << ", graphicBuffer dimension " << graphicBuffer->getWidth() << "x" |
| 125 | << graphicBuffer->getHeight() |
| 126 | << std::hex << std::setfill('0') |
| 127 | << ", format 0x" << std::setw(8) << graphicBuffer->getPixelFormat() |
| 128 | << ", usage 0x" << std::setw(16) << graphicBuffer->getUsage() |
| 129 | << std::dec << std::setfill(' ') |
| 130 | << ", stride " << graphicBuffer->getStride() |
| 131 | << ", generation " << graphicBuffer->getGenerationNumber(); |
| 132 | |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 133 | C2SyncVariables *syncVar = syncMem ? syncMem->mem() : nullptr; |
| 134 | status_t result = OK; |
| 135 | if (syncVar) { |
| 136 | syncVar->lock(); |
| 137 | if (!syncVar->isDequeueableLocked() || |
| 138 | syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_SWITCHING) { |
| 139 | syncVar->unlock(); |
| 140 | LOG(WARNING) << "attachToBufferQueue -- attachBuffer failed: " |
| 141 | "status = " << INVALID_OPERATION << "."; |
| 142 | return INVALID_OPERATION; |
| 143 | } |
Sungtak Lee | 849fb75 | 2023-11-14 20:46:33 +0000 | [diff] [blame^] | 144 | syncVar->notifyDequeuedLocked(); |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 145 | syncVar->unlock(); |
Sungtak Lee | 849fb75 | 2023-11-14 20:46:33 +0000 | [diff] [blame^] | 146 | result = igbp->attachBuffer(bqSlot, graphicBuffer); |
| 147 | if (result != OK) { |
| 148 | syncVar->lock(); |
| 149 | syncVar->notifyQueuedLocked(); |
| 150 | syncVar->unlock(); |
| 151 | } |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 152 | } else { |
| 153 | result = igbp->attachBuffer(bqSlot, graphicBuffer); |
| 154 | } |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 155 | if (result != OK) { |
| 156 | LOG(WARNING) << "attachToBufferQueue -- attachBuffer failed: " |
| 157 | "status = " << result << "."; |
| 158 | return result; |
| 159 | } |
| 160 | LOG(VERBOSE) << "attachToBufferQueue -- attachBuffer returned slot #" |
| 161 | << *bqSlot << "."; |
| 162 | return OK; |
| 163 | } |
| 164 | |
| 165 | bool getBufferQueueAssignment(const C2ConstGraphicBlock& block, |
| 166 | uint32_t* generation, |
| 167 | uint64_t* bqId, |
| 168 | int32_t* bqSlot) { |
| 169 | return _C2BlockFactory::GetBufferQueueData( |
| 170 | _C2BlockFactory::GetGraphicBlockPoolData(block), |
| 171 | generation, bqId, bqSlot); |
| 172 | } |
| 173 | |
| 174 | } // unnamed namespace |
| 175 | |
| 176 | OutputBufferQueue::OutputBufferQueue() |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 177 | : mGeneration{0}, mBqId{0}, mStopped{false} { |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 178 | } |
| 179 | |
| 180 | OutputBufferQueue::~OutputBufferQueue() { |
| 181 | } |
| 182 | |
| 183 | bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp, |
| 184 | uint32_t generation, |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 185 | uint64_t bqId, |
Sungtak Lee | db14cba | 2021-04-10 00:50:23 -0700 | [diff] [blame] | 186 | int maxDequeueBufferCount, |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 187 | std::shared_ptr<V1_2::SurfaceSyncObj> *syncObj) { |
Chih-Yu Huang | b5ec89e | 2021-02-09 17:37:32 +0900 | [diff] [blame] | 188 | uint64_t consumerUsage = 0; |
Sungtak Lee | b638802 | 2021-07-21 00:40:26 -0700 | [diff] [blame] | 189 | if (igbp && igbp->getConsumerUsage(&consumerUsage) != OK) { |
Chih-Yu Huang | b5ec89e | 2021-02-09 17:37:32 +0900 | [diff] [blame] | 190 | ALOGW("failed to get consumer usage"); |
| 191 | } |
| 192 | |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 193 | // TODO : Abstract creation process into C2SurfaceSyncMemory class. |
| 194 | // use C2LinearBlock instead ashmem. |
| 195 | std::shared_ptr<C2SurfaceSyncMemory> syncMem; |
| 196 | if (syncObj && igbp) { |
| 197 | bool mapped = false; |
| 198 | int memFd = ashmem_create_region("C2SurfaceMem", sizeof(C2SyncVariables)); |
| 199 | size_t memSize = memFd < 0 ? 0 : ashmem_get_size_region(memFd); |
| 200 | if (memSize > 0) { |
| 201 | syncMem = C2SurfaceSyncMemory::Create(memFd, memSize); |
| 202 | if (syncMem) { |
| 203 | mapped = true; |
| 204 | *syncObj = std::make_shared<V1_2::SurfaceSyncObj>(); |
| 205 | (*syncObj)->syncMemory = syncMem->handle(); |
| 206 | (*syncObj)->bqId = bqId; |
| 207 | (*syncObj)->generationId = generation; |
| 208 | (*syncObj)->consumerUsage = consumerUsage; |
| 209 | ALOGD("C2SurfaceSyncMemory created %zu(%zu)", sizeof(C2SyncVariables), memSize); |
| 210 | } |
| 211 | } |
| 212 | if (!mapped) { |
| 213 | if (memFd >= 0) { |
| 214 | ::close(memFd); |
| 215 | } |
| 216 | ALOGW("SurfaceSyncObj creation failure"); |
| 217 | } |
| 218 | } |
| 219 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 220 | size_t tryNum = 0; |
| 221 | size_t success = 0; |
| 222 | sp<GraphicBuffer> buffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; |
| 223 | std::weak_ptr<_C2BlockPoolData> |
| 224 | poolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS]; |
Sungtak Lee | 3cc67e7 | 2023-05-08 17:00:05 +0000 | [diff] [blame] | 225 | std::shared_ptr<C2SurfaceSyncMemory> oldMem; |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 226 | { |
| 227 | std::scoped_lock<std::mutex> l(mMutex); |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 228 | bool stopped = mStopped; |
| 229 | mStopped = false; |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 230 | if (generation == mGeneration) { |
Sungtak Lee | db14cba | 2021-04-10 00:50:23 -0700 | [diff] [blame] | 231 | // case of old BlockPool destruction |
| 232 | C2SyncVariables *var = mSyncMem ? mSyncMem->mem() : nullptr; |
George Burgess IV | 3defea7 | 2021-04-23 18:43:57 -0700 | [diff] [blame] | 233 | if (syncObj && var) { |
Sungtak Lee | db14cba | 2021-04-10 00:50:23 -0700 | [diff] [blame] | 234 | *syncObj = std::make_shared<V1_2::SurfaceSyncObj>(); |
| 235 | (*syncObj)->bqId = bqId; |
| 236 | (*syncObj)->syncMemory = mSyncMem->handle(); |
| 237 | (*syncObj)->generationId = generation; |
| 238 | (*syncObj)->consumerUsage = consumerUsage; |
| 239 | mMaxDequeueBufferCount = maxDequeueBufferCount; |
| 240 | var->lock(); |
| 241 | var->setSyncStatusLocked(C2SyncVariables::STATUS_INIT); |
| 242 | var->setInitialDequeueCountLocked(mMaxDequeueBufferCount, 0); |
| 243 | var->unlock(); |
| 244 | } |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 245 | return false; |
| 246 | } |
Sungtak Lee | 3cc67e7 | 2023-05-08 17:00:05 +0000 | [diff] [blame] | 247 | oldMem = mSyncMem; |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 248 | C2SyncVariables *oldSync = mSyncMem ? mSyncMem->mem() : nullptr; |
| 249 | if (oldSync) { |
| 250 | oldSync->lock(); |
| 251 | oldSync->setSyncStatusLocked(C2SyncVariables::STATUS_SWITCHING); |
| 252 | oldSync->unlock(); |
| 253 | } |
| 254 | mSyncMem.reset(); |
| 255 | if (syncMem) { |
| 256 | mSyncMem = syncMem; |
| 257 | } |
| 258 | C2SyncVariables *newSync = mSyncMem ? mSyncMem->mem() : nullptr; |
| 259 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 260 | mIgbp = igbp; |
| 261 | mGeneration = generation; |
| 262 | mBqId = bqId; |
| 263 | mOwner = std::make_shared<int>(0); |
Sungtak Lee | db14cba | 2021-04-10 00:50:23 -0700 | [diff] [blame] | 264 | mMaxDequeueBufferCount = maxDequeueBufferCount; |
Sungtak Lee | b638802 | 2021-07-21 00:40:26 -0700 | [diff] [blame] | 265 | if (igbp == nullptr) { |
| 266 | return false; |
| 267 | } |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 268 | for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) { |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 269 | if (mBqId == 0 || !mBuffers[i] || stopped) { |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 270 | continue; |
| 271 | } |
| 272 | std::shared_ptr<_C2BlockPoolData> data = mPoolDatas[i].lock(); |
| 273 | if (!data || |
| 274 | !_C2BlockFactory::BeginAttachBlockToBufferQueue(data)) { |
| 275 | continue; |
| 276 | } |
| 277 | ++tryNum; |
| 278 | int bqSlot; |
Chih-Yu Huang | b5ec89e | 2021-02-09 17:37:32 +0900 | [diff] [blame] | 279 | |
| 280 | // Update buffer's generation and usage. |
| 281 | if ((mBuffers[i]->getUsage() & consumerUsage) != consumerUsage) { |
| 282 | mBuffers[i] = new GraphicBuffer( |
| 283 | mBuffers[i]->handle, GraphicBuffer::CLONE_HANDLE, |
| 284 | mBuffers[i]->width, mBuffers[i]->height, |
| 285 | mBuffers[i]->format, mBuffers[i]->layerCount, |
| 286 | mBuffers[i]->getUsage() | consumerUsage, |
| 287 | mBuffers[i]->stride); |
| 288 | if (mBuffers[i]->initCheck() != OK) { |
| 289 | ALOGW("%s() failed to update usage, original usage=%" PRIx64 |
| 290 | ", consumer usage=%" PRIx64, |
| 291 | __func__, mBuffers[i]->getUsage(), consumerUsage); |
| 292 | continue; |
| 293 | } |
| 294 | } |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 295 | mBuffers[i]->setGenerationNumber(generation); |
Chih-Yu Huang | b5ec89e | 2021-02-09 17:37:32 +0900 | [diff] [blame] | 296 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 297 | status_t result = igbp->attachBuffer(&bqSlot, mBuffers[i]); |
| 298 | if (result != OK) { |
| 299 | continue; |
| 300 | } |
| 301 | bool attach = |
| 302 | _C2BlockFactory::EndAttachBlockToBufferQueue( |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 303 | data, mOwner, getHgbp(mIgbp), mSyncMem, |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 304 | generation, bqId, bqSlot); |
| 305 | if (!attach) { |
| 306 | igbp->cancelBuffer(bqSlot, Fence::NO_FENCE); |
| 307 | continue; |
| 308 | } |
| 309 | buffers[bqSlot] = mBuffers[i]; |
| 310 | poolDatas[bqSlot] = data; |
| 311 | ++success; |
| 312 | } |
| 313 | for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) { |
| 314 | mBuffers[i] = buffers[i]; |
| 315 | mPoolDatas[i] = poolDatas[i]; |
| 316 | } |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 317 | if (newSync) { |
Sungtak Lee | db14cba | 2021-04-10 00:50:23 -0700 | [diff] [blame] | 318 | newSync->lock(); |
| 319 | newSync->setInitialDequeueCountLocked(mMaxDequeueBufferCount, success); |
| 320 | newSync->unlock(); |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 321 | } |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 322 | } |
Sungtak Lee | 3cc67e7 | 2023-05-08 17:00:05 +0000 | [diff] [blame] | 323 | { |
| 324 | std::scoped_lock<std::mutex> l(mOldMutex); |
| 325 | mOldMem = oldMem; |
| 326 | } |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 327 | ALOGD("remote graphic buffer migration %zu/%zu", |
| 328 | success, tryNum); |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 329 | return true; |
| 330 | } |
| 331 | |
Sungtak Lee | 3cc67e7 | 2023-05-08 17:00:05 +0000 | [diff] [blame] | 332 | void OutputBufferQueue::expireOldWaiters() { |
| 333 | std::scoped_lock<std::mutex> l(mOldMutex); |
| 334 | if (mOldMem) { |
| 335 | C2SyncVariables *oldSync = mOldMem->mem(); |
| 336 | if (oldSync) { |
| 337 | oldSync->notifyAll(); |
| 338 | } |
| 339 | mOldMem.reset(); |
| 340 | } |
| 341 | } |
| 342 | |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 343 | void OutputBufferQueue::stop() { |
Sungtak Lee | c0c0596 | 2023-10-25 08:14:13 +0000 | [diff] [blame] | 344 | std::shared_ptr<C2SurfaceSyncMemory> oldMem; |
| 345 | { |
| 346 | std::scoped_lock<std::mutex> l(mMutex); |
| 347 | if (mStopped) { |
| 348 | return; |
| 349 | } |
| 350 | mStopped = true; |
| 351 | mOwner.reset(); // destructor of the block will not trigger IGBP::cancel() |
| 352 | // basically configuring null surface |
| 353 | oldMem = mSyncMem; |
| 354 | mSyncMem.reset(); |
| 355 | mIgbp.clear(); |
| 356 | mGeneration = 0; |
| 357 | mBqId = 0; |
| 358 | } |
| 359 | { |
| 360 | std::scoped_lock<std::mutex> l(mOldMutex); |
| 361 | mOldMem = oldMem; |
| 362 | } |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 363 | } |
| 364 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 365 | bool OutputBufferQueue::registerBuffer(const C2ConstGraphicBlock& block) { |
| 366 | std::shared_ptr<_C2BlockPoolData> data = |
| 367 | _C2BlockFactory::GetGraphicBlockPoolData(block); |
| 368 | if (!data) { |
| 369 | return false; |
| 370 | } |
| 371 | std::scoped_lock<std::mutex> l(mMutex); |
| 372 | |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 373 | if (!mIgbp || mStopped) { |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 374 | return false; |
| 375 | } |
| 376 | |
| 377 | uint32_t oldGeneration; |
| 378 | uint64_t oldId; |
| 379 | int32_t oldSlot; |
| 380 | // If the block is not bufferqueue-based, do nothing. |
| 381 | if (!_C2BlockFactory::GetBufferQueueData( |
| 382 | data, &oldGeneration, &oldId, &oldSlot) || (oldId == 0)) { |
| 383 | return false; |
| 384 | } |
| 385 | // If the block's bqId is the same as the desired bqId, just hold. |
| 386 | if ((oldId == mBqId) && (oldGeneration == mGeneration)) { |
| 387 | LOG(VERBOSE) << "holdBufferQueueBlock -- import without attaching:" |
| 388 | << " bqId " << oldId |
| 389 | << ", bqSlot " << oldSlot |
| 390 | << ", generation " << mGeneration |
| 391 | << "."; |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 392 | _C2BlockFactory::HoldBlockFromBufferQueue(data, mOwner, getHgbp(mIgbp), mSyncMem); |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 393 | mPoolDatas[oldSlot] = data; |
| 394 | mBuffers[oldSlot] = createGraphicBuffer(block); |
| 395 | mBuffers[oldSlot]->setGenerationNumber(mGeneration); |
| 396 | return true; |
| 397 | } |
| 398 | int32_t d = (int32_t) mGeneration - (int32_t) oldGeneration; |
| 399 | LOG(WARNING) << "receiving stale buffer: generation " |
| 400 | << mGeneration << " , diff " << d << " : slot " |
| 401 | << oldSlot; |
| 402 | return false; |
| 403 | } |
| 404 | |
| 405 | status_t OutputBufferQueue::outputBuffer( |
| 406 | const C2ConstGraphicBlock& block, |
| 407 | const BnGraphicBufferProducer::QueueBufferInput& input, |
| 408 | BnGraphicBufferProducer::QueueBufferOutput* output) { |
| 409 | uint32_t generation; |
| 410 | uint64_t bqId; |
| 411 | int32_t bqSlot; |
Arun Johnson | 7ba6707 | 2023-11-06 22:23:04 +0000 | [diff] [blame] | 412 | ScopedTrace trace(ATRACE_TAG,"Codec2-OutputBufferQueue::outputBuffer"); |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 413 | bool display = V1_0::utils::displayBufferQueueBlock(block); |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 414 | if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) || |
| 415 | bqId == 0) { |
| 416 | // Block not from bufferqueue -- it must be attached before queuing. |
| 417 | |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 418 | std::shared_ptr<C2SurfaceSyncMemory> syncMem; |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 419 | mMutex.lock(); |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 420 | bool stopped = mStopped; |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 421 | sp<IGraphicBufferProducer> outputIgbp = mIgbp; |
| 422 | uint32_t outputGeneration = mGeneration; |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 423 | syncMem = mSyncMem; |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 424 | mMutex.unlock(); |
| 425 | |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 426 | if (stopped) { |
| 427 | LOG(INFO) << "outputBuffer -- already stopped."; |
| 428 | return DEAD_OBJECT; |
| 429 | } |
| 430 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 431 | status_t status = attachToBufferQueue( |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 432 | block, outputIgbp, outputGeneration, &bqSlot, syncMem); |
| 433 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 434 | if (status != OK) { |
| 435 | LOG(WARNING) << "outputBuffer -- attaching failed."; |
| 436 | return INVALID_OPERATION; |
| 437 | } |
| 438 | |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 439 | auto syncVar = syncMem ? syncMem->mem() : nullptr; |
| 440 | if(syncVar) { |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 441 | status = outputIgbp->queueBuffer(static_cast<int>(bqSlot), |
| 442 | input, output); |
| 443 | if (status == OK) { |
Sungtak Lee | 849fb75 | 2023-11-14 20:46:33 +0000 | [diff] [blame^] | 444 | syncVar->lock(); |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 445 | syncVar->notifyQueuedLocked(); |
Sungtak Lee | 849fb75 | 2023-11-14 20:46:33 +0000 | [diff] [blame^] | 446 | syncVar->unlock(); |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 447 | } |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 448 | } else { |
| 449 | status = outputIgbp->queueBuffer(static_cast<int>(bqSlot), |
| 450 | input, output); |
| 451 | } |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 452 | if (status != OK) { |
| 453 | LOG(ERROR) << "outputBuffer -- queueBuffer() failed " |
| 454 | "on non-bufferqueue-based block. " |
| 455 | "Error = " << status << "."; |
| 456 | return status; |
| 457 | } |
| 458 | return OK; |
| 459 | } |
| 460 | |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 461 | std::shared_ptr<C2SurfaceSyncMemory> syncMem; |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 462 | mMutex.lock(); |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 463 | bool stopped = mStopped; |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 464 | sp<IGraphicBufferProducer> outputIgbp = mIgbp; |
| 465 | uint32_t outputGeneration = mGeneration; |
| 466 | uint64_t outputBqId = mBqId; |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 467 | syncMem = mSyncMem; |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 468 | mMutex.unlock(); |
| 469 | |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 470 | if (stopped) { |
| 471 | LOG(INFO) << "outputBuffer -- already stopped."; |
| 472 | return DEAD_OBJECT; |
| 473 | } |
| 474 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 475 | if (!outputIgbp) { |
| 476 | LOG(VERBOSE) << "outputBuffer -- output surface is null."; |
| 477 | return NO_INIT; |
| 478 | } |
| 479 | |
| 480 | if (!display) { |
| 481 | LOG(WARNING) << "outputBuffer -- cannot display " |
| 482 | "bufferqueue-based block to the bufferqueue."; |
| 483 | return UNKNOWN_ERROR; |
| 484 | } |
| 485 | if (bqId != outputBqId || generation != outputGeneration) { |
| 486 | int32_t diff = (int32_t) outputGeneration - (int32_t) generation; |
| 487 | LOG(WARNING) << "outputBuffer -- buffers from old generation to " |
| 488 | << outputGeneration << " , diff: " << diff |
| 489 | << " , slot: " << bqSlot; |
| 490 | return DEAD_OBJECT; |
| 491 | } |
| 492 | |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 493 | auto syncVar = syncMem ? syncMem->mem() : nullptr; |
| 494 | status_t status = OK; |
| 495 | if (syncVar) { |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 496 | status = outputIgbp->queueBuffer(static_cast<int>(bqSlot), |
| 497 | input, output); |
| 498 | if (status == OK) { |
Sungtak Lee | 849fb75 | 2023-11-14 20:46:33 +0000 | [diff] [blame^] | 499 | syncVar->lock(); |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 500 | syncVar->notifyQueuedLocked(); |
Sungtak Lee | 849fb75 | 2023-11-14 20:46:33 +0000 | [diff] [blame^] | 501 | syncVar->unlock(); |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 502 | } |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 503 | } else { |
| 504 | status = outputIgbp->queueBuffer(static_cast<int>(bqSlot), |
| 505 | input, output); |
| 506 | } |
| 507 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 508 | if (status != OK) { |
| 509 | LOG(ERROR) << "outputBuffer -- queueBuffer() failed " |
| 510 | "on bufferqueue-based block. " |
| 511 | "Error = " << status << "."; |
| 512 | return status; |
| 513 | } |
| 514 | return OK; |
| 515 | } |
| 516 | |
Brian Lindahl | 932bf60 | 2023-03-09 11:59:48 -0700 | [diff] [blame] | 517 | void OutputBufferQueue::pollForRenderedFrames(FrameEventHistoryDelta* delta) { |
| 518 | if (mIgbp) { |
| 519 | mIgbp->getFrameTimestamps(delta); |
| 520 | } |
| 521 | } |
| 522 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 523 | void OutputBufferQueue::holdBufferQueueBlocks( |
| 524 | const std::list<std::unique_ptr<C2Work>>& workList) { |
| 525 | forEachBlock(workList, |
| 526 | std::bind(&OutputBufferQueue::registerBuffer, |
| 527 | this, std::placeholders::_1)); |
| 528 | } |
| 529 | |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 530 | void OutputBufferQueue::updateMaxDequeueBufferCount(int maxDequeueBufferCount) { |
| 531 | mMutex.lock(); |
| 532 | mMaxDequeueBufferCount = maxDequeueBufferCount; |
| 533 | auto syncVar = mSyncMem ? mSyncMem->mem() : nullptr; |
Sungtak Lee | c7da7a0 | 2022-05-05 08:45:33 +0000 | [diff] [blame] | 534 | if (syncVar && !mStopped) { |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 535 | syncVar->lock(); |
| 536 | syncVar->updateMaxDequeueCountLocked(maxDequeueBufferCount); |
| 537 | syncVar->unlock(); |
| 538 | } |
| 539 | mMutex.unlock(); |
Sungtak Lee | db14cba | 2021-04-10 00:50:23 -0700 | [diff] [blame] | 540 | ALOGD("set max dequeue count %d from update", maxDequeueBufferCount); |
Sungtak Lee | a714f11 | 2021-03-16 05:40:03 -0700 | [diff] [blame] | 541 | } |
| 542 | |
Pawin Vongmasa | 586b198 | 2019-10-23 19:21:04 -0700 | [diff] [blame] | 543 | } // namespace c2 |
| 544 | } // namespace media |
| 545 | } // namespace hardware |
| 546 | } // namespace android |