1e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin/*
2e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * Copyright 2018, The Android Open Source Project
3e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin *
4e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * Licensed under the Apache License, Version 2.0 (the "License");
5e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * you may not use this file except in compliance with the License.
6e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * You may obtain a copy of the License at
7e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin *
8e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin *     http://www.apache.org/licenses/LICENSE-2.0
9e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin *
10e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * Unless required by applicable law or agreed to in writing, software
11e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * distributed under the License is distributed on an "AS IS" BASIS,
12e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * See the License for the specific language governing permissions and
14e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin * limitations under the License.
15e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin */
16e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
17e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin//#define LOG_NDEBUG 0
18e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin#define LOG_TAG "C2VdaBqBlockPool"
19e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
20e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin#include <errno.h>
21e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
22e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin#include <mutex>
23e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
24e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin#include <gui/BufferQueueDefs.h>
25e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin#include <utils/Log.h>
26e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
27e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin#include <C2AllocatorGralloc.h>
28e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin#include <C2BlockInternal.h>
29e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin#include <v4l2/C2VdaBqBlockPool.h>
30e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
31e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::AnwBuffer;
32e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::C2AndroidMemoryUsage;
33e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::Fence;
34e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::GraphicBuffer;
35e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::HGraphicBufferProducer;
36e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::hidl_handle;
37e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::IGraphicBufferProducer;
38e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::sp;
39e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::status_t;
40e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linusing ::android::hardware::graphics::common::V1_0::PixelFormat;
41e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
42e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linnamespace {
43e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
44e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin// The wait time for acquire fence in milliseconds.
45e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linconst int kFenceWaitTimeMs = 10;
46e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin// The timeout delay for dequeuing buffer from producer in nanoseconds.
47e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linconst int64_t kDequeueTimeoutNs = 10 * 1000 * 1000;
48e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
49e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin}  // namespace
50e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
51e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linstatic c2_status_t asC2Error(int32_t err) {
52e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    switch (err) {
53e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    case android::NO_ERROR:
54e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_OK;
55e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    case android::NO_INIT:
56e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_NO_INIT;
57e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    case android::BAD_VALUE:
58e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_BAD_VALUE;
59e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    case android::TIMED_OUT:
60e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_TIMED_OUT;
61e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    case android::WOULD_BLOCK:
62e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_BLOCKING;
63e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    case android::NO_MEMORY:
64e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_NO_MEMORY;
65e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    case -ETIME:
66e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_TIMED_OUT;  // for fence wait
67e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
68e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    return C2_CORRUPTED;
69e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin}
70e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
71e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih LinC2VdaBqBlockPool::C2VdaBqBlockPool(const std::shared_ptr<C2Allocator>& allocator,
72e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                                   const local_id_t localId)
73e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin      : C2BufferQueueBlockPool(allocator, localId),
74e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        mAllocator(allocator),
75e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        mLocalId(localId),
76e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        mMaxDequeuedBuffers(0u) {}
77e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
78e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih LinC2VdaBqBlockPool::~C2VdaBqBlockPool() {
79e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    std::lock_guard<std::mutex> lock(mMutex);
80e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    cancelAllBuffers();
81e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin}
82e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
83e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linc2_status_t C2VdaBqBlockPool::fetchGraphicBlock(
84e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
85e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        std::shared_ptr<C2GraphicBlock>* block /* nonnull */) {
86e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    std::lock_guard<std::mutex> lock(mMutex);
87e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
88e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (!mProducer) {
89e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        // Producer will not be configured in byte-buffer mode. Allocate buffers from allocator
90e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        // directly as a basic graphic block pool.
91e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        std::shared_ptr<C2GraphicAllocation> alloc;
92e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        c2_status_t err = mAllocator->newGraphicAllocation(width, height, format, usage, &alloc);
93e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (err != C2_OK) {
94e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return err;
95e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
96e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        *block = _C2BlockFactory::CreateGraphicBlock(alloc);
97e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_OK;
98e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
99e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
100e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    sp<Fence> fence = new Fence();
101e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    C2AndroidMemoryUsage androidUsage = usage;
102e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    int32_t status;
103e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    PixelFormat pixelFormat = static_cast<PixelFormat>(format);
104e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    int32_t slot;
105e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
106e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    mProducer->dequeueBuffer(
107e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            width, height, pixelFormat, androidUsage.asGrallocUsage(), true,
108e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            [&status, &slot, &fence](int32_t tStatus, int32_t tSlot, hidl_handle const& tFence,
109e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                                     HGraphicBufferProducer::FrameEventHistoryDelta const& tTs) {
110e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                status = tStatus;
111e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                slot = tSlot;
112e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                if (!android::conversion::convertTo(fence.get(), tFence) &&
113e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                    status == android::NO_ERROR) {
114e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                    status = android::BAD_VALUE;
115e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                }
116e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                (void)tTs;
117e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            });
118e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
119e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    // check dequeueBuffer return flag
120e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (status != android::NO_ERROR &&
121e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        status != IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
122e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (status == android::TIMED_OUT) {
123e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            // no buffer is available now, wait for another retry.
124e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGV("dequeueBuffer timed out, wait for retry...");
125e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return C2_TIMED_OUT;
126e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
127e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGE("dequeueBuffer failed: %d", status);
128e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return asC2Error(status);
129e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
130e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
131e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    // wait for acquire fence if we get one.
132e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    native_handle_t* nh = nullptr;
133e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    hidl_handle fenceHandle;
134e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (fence) {
135e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        android::conversion::wrapAs(&fenceHandle, &nh, *fence);
136e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        status_t fenceStatus = fence->wait(kFenceWaitTimeMs);
137e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (fenceStatus != android::NO_ERROR) {
138e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("buffer fence wait error: %d", fenceStatus);
139e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mProducer->cancelBuffer(slot, fenceHandle);
140e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            native_handle_delete(nh);
141e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return asC2Error(fenceStatus);
142e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
143e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
144e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
145e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    auto iter = mSlotAllocations.find(slot);
146e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (iter == mSlotAllocations.end()) {
147e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        // it's a new slot index, request for a new buffer.
148e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (mSlotAllocations.size() >= mMaxDequeuedBuffers) {
149e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("still get a new slot index but already allocated enough buffers.");
150e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mProducer->cancelBuffer(slot, fenceHandle);
151e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            native_handle_delete(nh);
152e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return C2_CORRUPTED;
153e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
154e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (status != IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
155e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("expect BUFFER_NEEDS_REALLOCATION flag but didn't get one.");
156e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mProducer->cancelBuffer(slot, fenceHandle);
157e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            native_handle_delete(nh);
158e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return C2_CORRUPTED;
159e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
160e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        sp<GraphicBuffer> slotBuffer = new GraphicBuffer();
161e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        mProducer->requestBuffer(
162e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                slot, [&status, &slotBuffer](int32_t tStatus, AnwBuffer const& tBuffer) {
163e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                    status = tStatus;
164e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                    if (!android::conversion::convertTo(slotBuffer.get(), tBuffer) &&
165e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                        status == android::NO_ERROR) {
166e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                        status = android::BAD_VALUE;
167e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                    }
168e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                });
169e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
170e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        // check requestBuffer return flag
171e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (status != android::NO_ERROR) {
172e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("requestBuffer failed: %d", status);
173e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mProducer->cancelBuffer(slot, fenceHandle);
174e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            native_handle_delete(nh);
175e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return asC2Error(status);
176e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
177e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        native_handle_delete(nh);
178e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
179e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        // convert GraphicBuffer to C2GraphicAllocation and wrap producer id and slot index
180e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        native_handle_t* grallocHandle = native_handle_clone(slotBuffer->handle);
181e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGV("buffer wraps { producer id: %" PRIu64 ", slot: %d }", mProducerId, slot);
182e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        C2Handle* c2Handle = android::WrapNativeCodec2GrallocHandle(
183e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                grallocHandle, slotBuffer->width, slotBuffer->height, slotBuffer->format,
184e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                slotBuffer->usage, slotBuffer->stride, mProducerId, slot);
185e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        native_handle_delete(grallocHandle);
186e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (!c2Handle) {
187e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("WrapNativeCodec2GrallocHandle failed");
188e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return C2_NO_MEMORY;
189e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
190e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
191e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        std::shared_ptr<C2GraphicAllocation> alloc;
192e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        c2_status_t err = mAllocator->priorGraphicAllocation(c2Handle, &alloc);
193e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (err != C2_OK) {
194e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("priorGraphicAllocation failed: %d", err);
195e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return err;
196e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
197e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
198e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        mSlotAllocations[slot] = std::move(alloc);
199e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (mSlotAllocations.size() == mMaxDequeuedBuffers) {
200e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            // already allocated enough buffers, set allowAllocation to false to restrict the
201e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            // eligible slots to allocated ones for future dequeue.
202e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            status = mProducer->allowAllocation(false);
203e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            if (status != android::NO_ERROR) {
204e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                ALOGE("allowAllocation(false) failed");
205e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                return asC2Error(status);
206e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            }
207e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
208e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    } else if (mSlotAllocations.size() < mMaxDequeuedBuffers) {
209e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGE("failed to allocate enough buffers");
210e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_BAD_STATE;
211e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
212e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
213e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    *block = _C2BlockFactory::CreateGraphicBlock(mSlotAllocations[slot]);
214e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    return C2_OK;
215e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin}
216e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
217e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linc2_status_t C2VdaBqBlockPool::requestNewBufferSet(int32_t bufferCount) {
218e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (bufferCount <= 0) {
219e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGE("Invalid requested buffer count = %d", bufferCount);
220e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_BAD_VALUE;
221e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
222e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
223e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    std::lock_guard<std::mutex> lock(mMutex);
224e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (!mProducer) {
225e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGD("No HGraphicBufferProducer is configured...");
226e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_NO_INIT;
227e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
228e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
229e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    // For dynamic resolution change, cancel all mapping buffers and discard references.
230e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    // Client needs to make sure all buffers are dequeued and owned by client before calling.
231e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    auto cancelStatus = cancelAllBuffers();
232e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (cancelStatus != C2_OK) {
233e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGE("cancelBuffer failed while requesting new buffer set...");
234e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return C2_CORRUPTED;
235e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
236e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
237e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    // TODO: should we query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS) and add it on?
238e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    int32_t status = mProducer->setMaxDequeuedBufferCount(bufferCount);
239e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (status != android::NO_ERROR) {
240e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGE("setMaxDequeuedBufferCount failed");
241e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return asC2Error(status);
242e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
243e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    mMaxDequeuedBuffers = static_cast<size_t>(bufferCount);
244e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
245e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    status = mProducer->allowAllocation(true);
246e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (status != android::NO_ERROR) {
247e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGE("allowAllocation(true) failed");
248e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return asC2Error(status);
249e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
250e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    return C2_OK;
251e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin}
252e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
253e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linvoid C2VdaBqBlockPool::configureProducer(const sp<HGraphicBufferProducer>& producer) {
254e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    ALOGV("configureProducer");
255e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    std::lock_guard<std::mutex> lock(mMutex);
256e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    // TODO: handle producer change request (client changes surface) while codec is running.
257e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (mProducer) {
258e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        ALOGE("Not allowed to reset HGraphicBufferProducer");
259e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        return;
260e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
261e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
262e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    mProducer = producer;
263e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    if (producer) {
264e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        int32_t status;
265e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        producer->getUniqueId(
266e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                [&status, &producerId = mProducerId](int32_t tStatus, int64_t tProducerId) {
267e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                    status = tStatus;
268e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                    producerId = tProducerId;
269e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin                });
270e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (status != android::NO_ERROR) {
271e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("getUniqueId failed");
272e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mProducer = nullptr;
273e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mProducerId = 0;
274e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return;
275e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
276e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        status = producer->setDequeueTimeout(kDequeueTimeoutNs);
277e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (status != android::NO_ERROR) {
278e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("setDequeueTimeout failed");
279e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mProducer = nullptr;
280e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mProducerId = 0;
281e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return;
282e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
283e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    } else {
284e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        mProducerId = 0;
285e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
286e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    mSlotAllocations.clear();
287e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin}
288e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin
289e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Linc2_status_t C2VdaBqBlockPool::cancelAllBuffers() {
290e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    int32_t lastError = android::NO_ERROR;
291e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    for (const auto& elem : mSlotAllocations) {
292e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        int32_t slot = elem.first;
293e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        sp<Fence> fence(Fence::NO_FENCE);
294e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        native_handle_t* nh = nullptr;
295e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        hidl_handle fenceHandle;
296e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        android::conversion::wrapAs(&fenceHandle, &nh, *fence);
297e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        int32_t status = mProducer->cancelBuffer(slot, fenceHandle);
298e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        native_handle_delete(nh);
299e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (status == android::NO_INIT) {
300e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            // Producer may be disconnected during the loop of cancelBuffer (especially in the
301e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            // destruction state). Break the loop and return immediately.
302e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            mSlotAllocations.clear();
303e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            return C2_NO_INIT;
304e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
305e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        if (status != android::NO_ERROR) {
306e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            ALOGE("cancelBuffer failed at slot = %d, err: %d", slot, status);
307e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin            lastError = status;
308e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin        }
309e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    }
310e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    mSlotAllocations.clear();
311e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin    return asC2Error(lastError);
312e93355155764df62c1bb71f67a0796b33fe7a452Pin-chih Lin}
313