Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b85e5d70 authored by Wonsik Kim's avatar Wonsik Kim Committed by Automerger Merge Worker
Browse files

Merge "CCodec: split preparation and request of initial input buffers" into...

Merge "CCodec: split preparation and request of initial input buffers" into tm-dev am: 8fed6de7 am: 48fa096b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/18530392



Change-Id: I0796d47926e0aee21128e2d7b3a05d6a90fc0f9c
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 52a9549c 48fa096b
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -1826,13 +1826,20 @@ void CCodec::start() {
        return;
    }

    mCallback->onStartCompleted();

    err2 = mChannel->requestInitialInputBuffers();
    // preparation of input buffers may not succeed due to the lack of
    // memory; returning correct error code (NO_MEMORY) as an error allows
    // MediaCodec to try reclaim and restart codec gracefully.
    std::map<size_t, sp<MediaCodecBuffer>> clientInputBuffers;
    err2 = mChannel->prepareInitialInputBuffers(&clientInputBuffers);
    if (err2 != OK) {
        ALOGE("Initial request for Input Buffers failed");
        ALOGE("Initial preparation for Input Buffers failed");
        mCallback->onError(err2, ACTION_CODE_FATAL);
        return;
    }

    mCallback->onStartCompleted();

    mChannel->requestInitialInputBuffers(std::move(clientInputBuffers));
}

void CCodec::initiateShutdown(bool keepComponentAllocated) {
@@ -2126,11 +2133,14 @@ void CCodec::signalResume() {
        state->set(RUNNING);
    }

    status_t err = mChannel->requestInitialInputBuffers();
    std::map<size_t, sp<MediaCodecBuffer>> clientInputBuffers;
    status_t err = mChannel->prepareInitialInputBuffers(&clientInputBuffers);
    if (err != OK) {
        ALOGE("Resume request for Input Buffers failed");
        mCallback->onError(err, ACTION_CODE_FATAL);
        return;
    }
    mChannel->requestInitialInputBuffers(std::move(clientInputBuffers));
}

void CCodec::signalSetParameters(const sp<AMessage> &msg) {
+39 −40
Original line number Diff line number Diff line
@@ -1470,54 +1470,47 @@ status_t CCodecBufferChannel::start(
    return OK;
}

status_t CCodecBufferChannel::requestInitialInputBuffers() {
status_t CCodecBufferChannel::prepareInitialInputBuffers(
        std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers) {
    if (mInputSurface) {
        return OK;
    }

    C2StreamBufferTypeSetting::output oStreamFormat(0u);
    C2PrependHeaderModeSetting prepend(PREPEND_HEADER_TO_NONE);
    c2_status_t err = mComponent->query({ &oStreamFormat, &prepend }, {}, C2_DONT_BLOCK, nullptr);
    if (err != C2_OK && err != C2_BAD_INDEX) {
        return UNKNOWN_ERROR;
    }
    size_t numInputSlots = mInput.lock()->numSlots;

    struct ClientInputBuffer {
        size_t index;
        sp<MediaCodecBuffer> buffer;
        size_t capacity;
    };
    std::list<ClientInputBuffer> clientInputBuffers;

    {
        Mutexed<Input>::Locked input(mInput);
        while (clientInputBuffers.size() < numInputSlots) {
            ClientInputBuffer clientInputBuffer;
            if (!input->buffers->requestNewBuffer(&clientInputBuffer.index,
                                                  &clientInputBuffer.buffer)) {
        while (clientInputBuffers->size() < numInputSlots) {
            size_t index;
            sp<MediaCodecBuffer> buffer;
            if (!input->buffers->requestNewBuffer(&index, &buffer)) {
                break;
            }
            clientInputBuffer.capacity = clientInputBuffer.buffer->capacity();
            clientInputBuffers.emplace_back(std::move(clientInputBuffer));
            clientInputBuffers->emplace(index, buffer);
        }
    }
    if (clientInputBuffers.empty()) {
    if (clientInputBuffers->empty()) {
        ALOGW("[%s] start: cannot allocate memory at all", mName);
        return NO_MEMORY;
    } else if (clientInputBuffers.size() < numInputSlots) {
    } else if (clientInputBuffers->size() < numInputSlots) {
        ALOGD("[%s] start: cannot allocate memory for all slots, "
              "only %zu buffers allocated",
              mName, clientInputBuffers.size());
              mName, clientInputBuffers->size());
    } else {
        ALOGV("[%s] %zu initial input buffers available",
              mName, clientInputBuffers.size());
              mName, clientInputBuffers->size());
    }
    return OK;
}

status_t CCodecBufferChannel::requestInitialInputBuffers(
        std::map<size_t, sp<MediaCodecBuffer>> &&clientInputBuffers) {
    C2StreamBufferTypeSetting::output oStreamFormat(0u);
    C2PrependHeaderModeSetting prepend(PREPEND_HEADER_TO_NONE);
    c2_status_t err = mComponent->query({ &oStreamFormat, &prepend }, {}, C2_DONT_BLOCK, nullptr);
    if (err != C2_OK && err != C2_BAD_INDEX) {
        return UNKNOWN_ERROR;
    }
    // Sort input buffers by their capacities in increasing order.
    clientInputBuffers.sort(
            [](const ClientInputBuffer& a, const ClientInputBuffer& b) {
                return a.capacity < b.capacity;
            });

    std::list<std::unique_ptr<C2Work>> flushedConfigs;
    mFlushedConfigs.lock()->swap(flushedConfigs);
@@ -1539,25 +1532,31 @@ status_t CCodecBufferChannel::requestInitialInputBuffers() {
        }
    }
    if (oStreamFormat.value == C2BufferData::LINEAR &&
            (!prepend || prepend.value == PREPEND_HEADER_TO_NONE)) {
        sp<MediaCodecBuffer> buffer = clientInputBuffers.front().buffer;
            (!prepend || prepend.value == PREPEND_HEADER_TO_NONE) &&
            !clientInputBuffers.empty()) {
        size_t minIndex = clientInputBuffers.begin()->first;
        sp<MediaCodecBuffer> minBuffer = clientInputBuffers.begin()->second;
        for (const auto &[index, buffer] : clientInputBuffers) {
            if (minBuffer->capacity() > buffer->capacity()) {
                minIndex = index;
                minBuffer = buffer;
            }
        }
        // WORKAROUND: Some apps expect CSD available without queueing
        //             any input. Queue an empty buffer to get the CSD.
        buffer->setRange(0, 0);
        buffer->meta()->clear();
        buffer->meta()->setInt64("timeUs", 0);
        if (queueInputBufferInternal(buffer) != OK) {
        minBuffer->setRange(0, 0);
        minBuffer->meta()->clear();
        minBuffer->meta()->setInt64("timeUs", 0);
        if (queueInputBufferInternal(minBuffer) != OK) {
            ALOGW("[%s] Error while queueing an empty buffer to get CSD",
                  mName);
            return UNKNOWN_ERROR;
        }
        clientInputBuffers.pop_front();
        clientInputBuffers.erase(minIndex);
    }

    for (const ClientInputBuffer& clientInputBuffer: clientInputBuffers) {
        mCallback->onInputBufferAvailable(
                clientInputBuffer.index,
                clientInputBuffer.buffer);
    for (const auto &[index, buffer] : clientInputBuffers) {
        mCallback->onInputBufferAvailable(index, buffer);
    }

    return OK;
+16 −2
Original line number Diff line number Diff line
@@ -130,9 +130,23 @@ public:
            bool buffersBoundToCodec);

    /**
     * Request initial input buffers to be filled by client.
     * Prepare initial input buffers to be filled by client.
     *
     * \param clientInputBuffers[out]   pointer to slot index -> buffer map.
     *                                  On success, it contains prepared
     *                                  initial input buffers.
     */
    status_t prepareInitialInputBuffers(
            std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers);

    /**
     * Request initial input buffers as prepared in clientInputBuffers.
     *
     * \param clientInputBuffers[in]    slot index -> buffer map with prepared
     *                                  initial input buffers.
     */
    status_t requestInitialInputBuffers();
    status_t requestInitialInputBuffers(
            std::map<size_t, sp<MediaCodecBuffer>> &&clientInputBuffers);

    /**
     * Stop queueing buffers to the component. This object should never queue