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

Commit dd248abd authored by Lajos Molnar's avatar Lajos Molnar
Browse files

stagefright: allow connecting to surfaces that attach buffers

Now that consumers can attach buffers to BufferQueues, we cannot
assert if an unknown buffer is dequeud, or if a buffer is dequeued
from a BufferQueue multiple times.

Also, when attaching to such surfaces, allocation must be enabled
as attach will lock for a free buffer slot.

Bug: 20885565
Change-Id: Ied466c5a848facf3149ad8bf0d18a0095da21e40
parent f52b2284
Loading
Loading
Loading
Loading
+49 −15
Original line number Diff line number Diff line
@@ -610,6 +610,9 @@ status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
        return err;
    }

    // need to enable allocation when attaching
    surface->getIGraphicBufferProducer()->allowAllocation(true);

    // for meta data mode, we move dequeud buffers to the new surface.
    // for non-meta mode, we must move all registered buffers
    for (size_t i = 0; i < buffers.size(); ++i) {
@@ -1046,26 +1049,57 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
        return NULL;
    }

    do {
        if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
            ALOGE("dequeueBuffer failed.");
            return NULL;
        }

    BufferInfo *oldest = NULL;
        bool stale = false;
        for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
        BufferInfo *info =
            &mBuffers[kPortIndexOutput].editItemAt(i);
            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);

            if (info->mGraphicBuffer != NULL &&
                info->mGraphicBuffer->handle == buf->handle) {
            CHECK_EQ((int)info->mStatus,
                     (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);

                // Since consumers can attach buffers to BufferQueues, it is possible
                // that a known yet stale buffer can return from a surface that we
                // once used.  We can simply ignore this as we have already dequeued
                // this buffer properly.  NOTE: this does not eliminate all cases,
                // e.g. it is possible that we have queued the valid buffer to the
                // NW, and a stale copy of the same buffer gets dequeued - which will
                // be treated as the valid buffer by ACodec.
                if (info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
                    ALOGI("dequeued stale buffer %p. discarding", buf);
                    stale = true;
                    break;
                }
                ALOGV("dequeued buffer %p", info->mGraphicBuffer->getNativeBuffer());
                info->mStatus = BufferInfo::OWNED_BY_US;

                return info;
            }
        }

        // It is also possible to receive a previously unregistered buffer
        // in non-meta mode. These should be treated as stale buffers. The
        // same is possible in meta mode, in which case, it will be treated
        // as a normal buffer, which is not desirable.
        // TODO: fix this.
        if (!stale && !mStoreMetaDataInOutputBuffers) {
            ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
            stale = true;
        }
        if (stale) {
            // TODO: detach stale buffer, but there is no API yet to do it.
            buf = NULL;
        }
    } while (buf == NULL);

    // get oldest undequeued buffer
    BufferInfo *oldest = NULL;
    for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
        BufferInfo *info =
            &mBuffers[kPortIndexOutput].editItemAt(i);
        if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
            (oldest == NULL ||
             // avoid potential issues from counter rolling over