GraphicBufferSource.cpp revision 910813bd66eaf0f6a72769c9b3fa9830dd100a19
1f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden/*
2f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * Copyright (C) 2013 The Android Open Source Project
3f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden *
4f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * Licensed under the Apache License, Version 2.0 (the "License");
5f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * you may not use this file except in compliance with the License.
6f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * You may obtain a copy of the License at
7f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden *
8f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden *      http://www.apache.org/licenses/LICENSE-2.0
9f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden *
10f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * Unless required by applicable law or agreed to in writing, software
11f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * distributed under the License is distributed on an "AS IS" BASIS,
12f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * See the License for the specific language governing permissions and
14f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden * limitations under the License.
15f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden */
16f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
17f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#define LOG_TAG "GraphicBufferSource"
18ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden//#define LOG_NDEBUG 0
19f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <utils/Log.h>
20f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
215e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian#include "GraphicBufferSource.h"
22f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
23f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <OMX_Core.h>
24f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <media/stagefright/foundation/ADebug.h>
25f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
265e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian#include <media/hardware/MetadataBufferType.h>
27f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <ui/GraphicBuffer.h>
28f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
29f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddennamespace android {
30f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
31f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenstatic const bool EXTRA_CHECK = true;
32f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
33f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
34f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenGraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance,
350c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount) :
36f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mInitCheck(UNKNOWN_ERROR),
37f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNodeInstance(nodeInstance),
38f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting(false),
39e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended(false),
40f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable(0),
41f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream(false),
42f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStreamSent(false) {
43f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
440c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("GraphicBufferSource w=%u h=%u c=%u",
450c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            bufferWidth, bufferHeight, bufferCount);
46f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
47f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (bufferWidth == 0 || bufferHeight == 0) {
480c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
49f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        mInitCheck = BAD_VALUE;
50f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
51f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
52f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
530c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    String8 name("GraphicBufferSource");
540c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
555e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian    mBufferQueue = new BufferQueue();
560c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mBufferQueue->setConsumerName(name);
57f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mBufferQueue->setDefaultBufferSize(bufferWidth, bufferHeight);
58f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER |
59f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            GRALLOC_USAGE_HW_TEXTURE);
60f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
610c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mInitCheck = mBufferQueue->setMaxAcquiredBufferCount(bufferCount);
620c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (mInitCheck != NO_ERROR) {
630c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
640c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                bufferCount, mInitCheck);
650c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return;
660c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
670c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
68f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
69f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // reference once the ctor ends, as that would cause the refcount of 'this'
70f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
71f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that's what we create.
72910813bd66eaf0f6a72769c9b3fa9830dd100a19Mathias Agopian    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
73910813bd66eaf0f6a72769c9b3fa9830dd100a19Mathias Agopian    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
74f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
755e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian    mInitCheck = mBufferQueue->consumerConnect(proxy, false);
760c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (mInitCheck != NO_ERROR) {
77f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("Error connecting to BufferQueue: %s (%d)",
780c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                strerror(-mInitCheck), mInitCheck);
79f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
80f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
81f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
820c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    CHECK(mInitCheck == NO_ERROR);
83f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
84f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
85f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenGraphicBufferSource::~GraphicBufferSource() {
86f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("~GraphicBufferSource");
870c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (mBufferQueue != NULL) {
880c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        status_t err = mBufferQueue->consumerDisconnect();
890c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        if (err != NO_ERROR) {
900c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            ALOGW("consumerDisconnect failed: %d", err);
910c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        }
92f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
93f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
94f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
95f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::omxExecuting() {
96f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
97f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("--> executing; avail=%d, codec vec size=%zd",
98f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mCodecBuffers.size());
99f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(!mExecuting);
100f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = true;
101f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
102f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Start by loading up as many buffers as possible.  We want to do this,
103f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // rather than just submit the first buffer, to avoid a degenerate case:
104f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // if all BQ buffers arrive before we start executing, and we only submit
105f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // one here, the other BQ buffers will just sit until we get notified
106f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that the codec buffer has been released.  We'd then acquire and
107f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // submit a single additional buffer, repeatedly, never using more than
108f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // one codec buffer simultaneously.  (We could instead try to submit
109f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // all BQ buffers whenever any codec buffer is freed, but if we get the
110f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // initial conditions right that will never be useful.)
1110c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    while (mNumFramesAvailable) {
1120c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        if (!fillCodecBuffer_l()) {
1130c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            ALOGV("stop load with frames available (codecAvail=%d)",
1140c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                    isCodecBufferAvailable_l());
1150c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            break;
1160c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        }
117f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
118f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
119f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("done loading initial frames, avail=%d", mNumFramesAvailable);
120f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
121f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If EOS has already been signaled, and there are no more frames to
122f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // submit, try to send EOS now as well.
123f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStream && mNumFramesAvailable == 0) {
124f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
125f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
126f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
127f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
128ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenvoid GraphicBufferSource::omxLoaded(){
129f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
130ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    if (!mExecuting) {
131ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        // This can happen if something failed very early.
132ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        ALOGW("Dropped back down to Loaded without Executing");
133ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    }
134f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
135ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    ALOGV("--> loaded; avail=%d eos=%d eosSent=%d",
136f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
137f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
138f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Codec is no longer executing.  Discard all codec-related state.
139f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.clear();
140f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
141f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //       are null; complain if not
142f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
143f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = false;
144f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
145f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
146f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) {
147f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
148f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
149f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
150f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen -- buffers can only be allocated when
151f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // transitioning from "loaded" to "idle".
152f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("addCodecBuffer: buffer added while executing");
153f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
154f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
155f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
156f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("addCodecBuffer h=%p size=%lu p=%p",
157f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->pBuffer);
158f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer codecBuffer;
159f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mHeader = header;
160f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.add(codecBuffer);
161f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
162f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
163f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) {
164f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
165f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
166f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mExecuting);  // could this happen if app stop()s early?
167f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
168f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findMatchingCodecBuffer_l(header);
169f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
170f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen.
171f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header);
172f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
173f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
174f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
175f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("codecBufferEmptied h=%p size=%lu filled=%lu p=%p",
176f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->nFilledLen,
177f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header->pBuffer);
178f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
179f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
180f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // header->nFilledLen may not be the original value, so we can't compare
181f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that to zero to see of this was the EOS buffer.  Instead we just
182f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // see if the GraphicBuffer reference was null, which should only ever
183f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // happen for EOS.
184f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (codecBuffer.mGraphicBuffer == NULL) {
1850c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        CHECK(mEndOfStream && mEndOfStreamSent);
186f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No GraphicBuffer to deal with, no additional input or output is
187f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // expected, so just return.
188f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
189f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
190f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
191f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (EXTRA_CHECK) {
192f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Pull the graphic buffer handle back out of the buffer, and confirm
193f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // that it matches expectations.
194f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        OMX_U8* data = header->pBuffer;
195f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        buffer_handle_t bufferHandle;
196f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        memcpy(&bufferHandle, data + 4, sizeof(buffer_handle_t));
197f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (bufferHandle != codecBuffer.mGraphicBuffer->handle) {
198f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            // should never happen
199f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
200f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                    bufferHandle, codecBuffer.mGraphicBuffer->handle);
201f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            CHECK(!"codecBufferEmptied: mismatched buffer");
202f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
203f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
204f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
205f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Find matching entry in our cached copy of the BufferQueue slots.
206f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If we find a match, release that slot.  If we don't, the BufferQueue
207f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // has dropped that GraphicBuffer, and there's nothing for us to release.
208d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    int id = codecBuffer.mBuf;
209d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    if (mBufferSlot[id] != NULL &&
210d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
211d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        ALOGV("cbi %d matches bq slot %d, handle=%p",
212d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                cbi, id, mBufferSlot[id]->handle);
213d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar
214d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferQueue->releaseBuffer(id, codecBuffer.mFrameNumber,
215d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
216d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    } else {
217f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
218f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                cbi);
219f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
220f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
221f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Mark the codec buffer as available by clearing the GraphicBuffer ref.
222f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mGraphicBuffer = NULL;
223f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
224f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mNumFramesAvailable) {
225f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Fill this codec buffer.
2260c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        CHECK(!mEndOfStreamSent);
2270c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("buffer freed, %d frames avail (eos=%d)",
2280c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                mNumFramesAvailable, mEndOfStream);
229f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
230f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else if (mEndOfStream) {
231f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No frames available, but EOS is pending, so use this buffer to
232f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // send that.
233f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("buffer freed, EOS pending");
234f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
235f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
236f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return;
237f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
238f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
239e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Hubervoid GraphicBufferSource::suspend(bool suspend) {
240e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    Mutex::Autolock autoLock(mMutex);
241e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
242e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (suspend) {
243e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        mSuspended = true;
244e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
245e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        while (mNumFramesAvailable > 0) {
246e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            BufferQueue::BufferItem item;
247e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            status_t err = mBufferQueue->acquireBuffer(&item, 0);
248e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
249e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
250e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                // shouldn't happen.
251e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: frame was not available");
252e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
253e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            } else if (err != OK) {
254e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: acquireBuffer returned err=%d", err);
255e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
256e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            }
257e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
258e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            --mNumFramesAvailable;
259e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
260e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
261e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
262e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
263e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return;
264e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
265e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
266e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended = false;
267e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber}
268e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
2690c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFaddenbool GraphicBufferSource::fillCodecBuffer_l() {
270f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mExecuting && mNumFramesAvailable > 0);
2710c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
272e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mSuspended) {
273e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return false;
274e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
275e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
276f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
277f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
278f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No buffers available, bail.
279f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("fillCodecBuffer_l: no codec buffers, avail now %d",
280f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                mNumFramesAvailable);
2810c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
2820c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
283f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
2840c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%d",
2850c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mNumFramesAvailable);
2860c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    BufferQueue::BufferItem item;
287656e86250cd68f7f362c50a4bc92a865e9deacbeAndy McFadden    status_t err = mBufferQueue->acquireBuffer(&item, 0);
2880c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
2890c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // shouldn't happen
2900c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: frame was not available");
2910c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
2920c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else if (err != OK) {
2930c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // now what? fake end-of-stream?
2940c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
2950c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
2960c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
297f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
2980c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mNumFramesAvailable--;
299f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3000c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // Wait for it to become available.
301d76442421eadfa73f2f3a9e50f6caf65b0dd1ce9Mathias Agopian    err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l");
3020c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err != OK) {
3030c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("failed to wait for buffer fence: %d", err);
3040c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // keep going
3050c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
306f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3070c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // If this is the first time we're seeing this buffer, add it to our
3080c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // slot table.
3090c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (item.mGraphicBuffer != NULL) {
3100c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf);
3110c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mBufferSlot[item.mBuf] = item.mGraphicBuffer;
3120c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
3130c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
314d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    err = submitBuffer_l(item, cbi);
3150c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err != OK) {
3160c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf);
317d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
318d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
3190c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else {
3200c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi);
321f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
322f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3230c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    return true;
324f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
325f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
326ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenstatus_t GraphicBufferSource::signalEndOfInputStream() {
327f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
328ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    ALOGV("signalEndOfInputStream: exec=%d avail=%d eos=%d",
329ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden            mExecuting, mNumFramesAvailable, mEndOfStream);
330ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
331ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    if (mEndOfStream) {
332ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        ALOGE("EOS was already signaled");
333ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        return INVALID_OPERATION;
334ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    }
335f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
336f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Set the end-of-stream flag.  If no frames are pending from the
337f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // BufferQueue, and a codec buffer is available, and we're executing,
338f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // we initiate the EOS from here.  Otherwise, we'll let
339f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // codecBufferEmptied() (or omxExecuting) do it.
340f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //
341f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note: if there are no pending frames and all codec buffers are
342f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // available, we *must* submit the EOS from here or we'll just
343f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // stall since no future events are expected.
344f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream = true;
345f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
346f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting && mNumFramesAvailable == 0) {
347f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
348f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
349ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
350ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    return OK;
351f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
352f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
353d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnarstatus_t GraphicBufferSource::submitBuffer_l(
354d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        const BufferQueue::BufferItem &item, int cbi) {
355f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("submitBuffer_l cbi=%d", cbi);
356f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
357d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf];
358d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mBuf = item.mBuf;
359d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mFrameNumber = item.mFrameNumber;
360f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
361f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
362f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(header->nAllocLen >= 4 + sizeof(buffer_handle_t));
363f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_U8* data = header->pBuffer;
364f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    const OMX_U32 type = kMetadataBufferTypeGrallocSource;
365f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    buffer_handle_t handle = codecBuffer.mGraphicBuffer->handle;
366f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    memcpy(data, &type, 4);
367f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    memcpy(data + 4, &handle, sizeof(buffer_handle_t));
368f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
369f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    status_t err = mNodeInstance->emptyDirectBuffer(header, 0,
370f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME,
371d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar            item.mTimestamp / 1000);
372f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
373f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err);
374f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        codecBuffer.mGraphicBuffer = NULL;
375f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return err;
376f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
377f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
378f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("emptyDirectBuffer succeeded, h=%p p=%p bufhandle=%p",
379f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->pBuffer, handle);
380f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return OK;
381f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
382f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
383f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::submitEndOfInputStream_l() {
384f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mEndOfStream);
385f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStreamSent) {
386f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("EOS already sent");
387f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
388f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
389f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
390f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
391f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
392f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: no codec buffers available");
393f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
394f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
395f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
396f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // We reject any additional incoming graphic buffers, so there's no need
397f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as
398f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // in-use.
399f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
400f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
401f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
402f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (EXTRA_CHECK) {
403f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Guard against implementations that don't check nFilledLen.
404f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        size_t fillLen = 4 + sizeof(buffer_handle_t);
405f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        CHECK(header->nAllocLen >= fillLen);
406f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        OMX_U8* data = header->pBuffer;
407f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        memset(data, 0xcd, fillLen);
408f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
409f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
410f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    uint64_t timestamp = 0; // does this matter?
411f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
412f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    status_t err = mNodeInstance->emptyDirectBuffer(header, /*offset*/ 0,
413f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            /*length*/ 0, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
414f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            timestamp);
415f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
416f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
417f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else {
418f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d",
419f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                header, cbi);
4200c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mEndOfStreamSent = true;
421f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
422f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
423f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
424f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findAvailableCodecBuffer_l() {
425f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mCodecBuffers.size() > 0);
426f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
427f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
428f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mGraphicBuffer == NULL) {
429f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
430f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
431f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
432f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
433f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
434f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
435f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findMatchingCodecBuffer_l(
436f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        const OMX_BUFFERHEADERTYPE* header) {
437f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
438f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mHeader == header) {
439f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
440f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
441f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
442f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
443f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
444f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
445f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
446f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::onFrameAvailable() {
447f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
448f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
4490c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("onFrameAvailable exec=%d avail=%d",
4500c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mExecuting, mNumFramesAvailable);
451f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
452e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mEndOfStream || mSuspended) {
453e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        if (mEndOfStream) {
454e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // This should only be possible if a new buffer was queued after
455e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // EOS was signaled, i.e. the app is misbehaving.
456e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
457e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGW("onFrameAvailable: EOS is set, ignoring frame");
458e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        } else {
459e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGV("onFrameAvailable: suspended, ignoring frame");
460e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
461f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
462f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        BufferQueue::BufferItem item;
463656e86250cd68f7f362c50a4bc92a865e9deacbeAndy McFadden        status_t err = mBufferQueue->acquireBuffer(&item, 0);
464f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (err == OK) {
465d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar            mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
466d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
467f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
468f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
469f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
470f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
471f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable++;
472f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
473f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
474f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
475f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
476f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
477f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
478f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
479f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::onBuffersReleased() {
480f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock lock(mMutex);
481f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
482f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    uint32_t slotMask;
483f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mBufferQueue->getReleasedBuffers(&slotMask) != NO_ERROR) {
484f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("onBuffersReleased: unable to get released buffer set");
485f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        slotMask = 0xffffffff;
486f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
487f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
488f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("onBuffersReleased: 0x%08x", slotMask);
489f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
490f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
491f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if ((slotMask & 0x01) != 0) {
492f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mBufferSlot[i] = NULL;
493f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
494f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        slotMask >>= 1;
495f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
496f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
497f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
498f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}  // namespace android
499