GraphicBufferSource.cpp revision 892e1b9ab055075ba9036fb7dd6404e9e0f2677a
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>
25a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber#include <media/stagefright/foundation/AMessage.h>
26f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
275e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian#include <media/hardware/MetadataBufferType.h>
28f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <ui/GraphicBuffer.h>
29f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
30f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddennamespace android {
31f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
32f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenstatic const bool EXTRA_CHECK = true;
33f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
34f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
35f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenGraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance,
360c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount) :
37f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mInitCheck(UNKNOWN_ERROR),
38f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNodeInstance(nodeInstance),
39f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting(false),
40e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended(false),
41f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable(0),
42f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream(false),
43a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mEndOfStreamSent(false),
44a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatAfterUs(-1ll),
45a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatLastFrameGeneration(0),
46a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferId(-1),
47a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferFrameNum(0),
48a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferUseCount(0),
49a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred(false) {
50f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
510c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("GraphicBufferSource w=%u h=%u c=%u",
520c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            bufferWidth, bufferHeight, bufferCount);
53f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
54f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (bufferWidth == 0 || bufferHeight == 0) {
550c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
56f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        mInitCheck = BAD_VALUE;
57f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
58f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
59f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
600c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    String8 name("GraphicBufferSource");
610c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
625e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian    mBufferQueue = new BufferQueue();
630c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mBufferQueue->setConsumerName(name);
64f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mBufferQueue->setDefaultBufferSize(bufferWidth, bufferHeight);
65f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER |
66f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            GRALLOC_USAGE_HW_TEXTURE);
67f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
680c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mInitCheck = mBufferQueue->setMaxAcquiredBufferCount(bufferCount);
690c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (mInitCheck != NO_ERROR) {
700c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
710c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                bufferCount, mInitCheck);
720c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return;
730c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
740c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
75f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
76f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // reference once the ctor ends, as that would cause the refcount of 'this'
77f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
78f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that's what we create.
79910813bd66eaf0f6a72769c9b3fa9830dd100a19Mathias Agopian    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
80910813bd66eaf0f6a72769c9b3fa9830dd100a19Mathias Agopian    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
81f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
825e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian    mInitCheck = mBufferQueue->consumerConnect(proxy, false);
830c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (mInitCheck != NO_ERROR) {
84f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("Error connecting to BufferQueue: %s (%d)",
850c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                strerror(-mInitCheck), mInitCheck);
86f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
87f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
88f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
890c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    CHECK(mInitCheck == NO_ERROR);
90f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
91f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
92f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenGraphicBufferSource::~GraphicBufferSource() {
93f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("~GraphicBufferSource");
940c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (mBufferQueue != NULL) {
950c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        status_t err = mBufferQueue->consumerDisconnect();
960c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        if (err != NO_ERROR) {
970c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            ALOGW("consumerDisconnect failed: %d", err);
980c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        }
99f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
100f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
101f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
102f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::omxExecuting() {
103f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
104f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("--> executing; avail=%d, codec vec size=%zd",
105f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mCodecBuffers.size());
106f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(!mExecuting);
107f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = true;
108f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
109f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Start by loading up as many buffers as possible.  We want to do this,
110f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // rather than just submit the first buffer, to avoid a degenerate case:
111f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // if all BQ buffers arrive before we start executing, and we only submit
112f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // one here, the other BQ buffers will just sit until we get notified
113f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that the codec buffer has been released.  We'd then acquire and
114f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // submit a single additional buffer, repeatedly, never using more than
115f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // one codec buffer simultaneously.  (We could instead try to submit
116f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // all BQ buffers whenever any codec buffer is freed, but if we get the
117f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // initial conditions right that will never be useful.)
1180c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    while (mNumFramesAvailable) {
1190c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        if (!fillCodecBuffer_l()) {
1200c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            ALOGV("stop load with frames available (codecAvail=%d)",
1210c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                    isCodecBufferAvailable_l());
1220c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            break;
1230c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        }
124f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
125f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
126f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("done loading initial frames, avail=%d", mNumFramesAvailable);
127f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
128f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If EOS has already been signaled, and there are no more frames to
129f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // submit, try to send EOS now as well.
130f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStream && mNumFramesAvailable == 0) {
131f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
132f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
133a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
134a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mRepeatAfterUs > 0ll && mLooper == NULL) {
135a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mReflector = new AHandlerReflector<GraphicBufferSource>(this);
136a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
137a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper = new ALooper;
138a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->registerHandler(mReflector);
139a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->start();
140a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
141a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (mLatestSubmittedBufferId >= 0) {
142a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            sp<AMessage> msg =
143a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                new AMessage(kWhatRepeatLastFrame, mReflector->id());
144a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
145a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            msg->setInt32("generation", ++mRepeatLastFrameGeneration);
146a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            msg->post(mRepeatAfterUs);
147a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
148a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
149f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
150f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
151ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Hubervoid GraphicBufferSource::omxIdle() {
152ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    ALOGV("omxIdle");
153ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
154ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    Mutex::Autolock autoLock(mMutex);
155ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
156ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    if (mExecuting) {
157ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber        // We are only interested in the transition from executing->idle,
158ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber        // not loaded->idle.
159892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber        mExecuting = false;
160ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    }
161ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber}
162ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
163ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenvoid GraphicBufferSource::omxLoaded(){
164f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
165ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    if (!mExecuting) {
166ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        // This can happen if something failed very early.
167ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        ALOGW("Dropped back down to Loaded without Executing");
168ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    }
169f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
170a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mLooper != NULL) {
171a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->unregisterHandler(mReflector->id());
172a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mReflector.clear();
173a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
174a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->stop();
175a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper.clear();
176a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
177a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
178ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    ALOGV("--> loaded; avail=%d eos=%d eosSent=%d",
179f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
180f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
181f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Codec is no longer executing.  Discard all codec-related state.
182f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.clear();
183f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
184f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //       are null; complain if not
185f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
186f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = false;
187f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
188f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
189f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) {
190f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
191f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
192f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
193f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen -- buffers can only be allocated when
194f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // transitioning from "loaded" to "idle".
195f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("addCodecBuffer: buffer added while executing");
196f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
197f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
198f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
199f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("addCodecBuffer h=%p size=%lu p=%p",
200f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->pBuffer);
201f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer codecBuffer;
202f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mHeader = header;
203f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.add(codecBuffer);
204f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
205f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
206f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) {
207f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
208f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
209892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber    if (!mExecuting) {
210892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber        return;
211892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber    }
212f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
213f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findMatchingCodecBuffer_l(header);
214f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
215f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen.
216f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header);
217f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
218f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
219f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
220f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("codecBufferEmptied h=%p size=%lu filled=%lu p=%p",
221f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->nFilledLen,
222f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header->pBuffer);
223f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
224f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
225f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // header->nFilledLen may not be the original value, so we can't compare
226f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that to zero to see of this was the EOS buffer.  Instead we just
227f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // see if the GraphicBuffer reference was null, which should only ever
228f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // happen for EOS.
229f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (codecBuffer.mGraphicBuffer == NULL) {
2305572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden        if (!(mEndOfStream && mEndOfStreamSent)) {
2315572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            // This can happen when broken code sends us the same buffer
2325572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            // twice in a row.
2335572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            ALOGE("ERROR: codecBufferEmptied on non-EOS null buffer "
2345572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden                    "(buffer emptied twice?)");
2355572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden        }
236f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No GraphicBuffer to deal with, no additional input or output is
237f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // expected, so just return.
238f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
239f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
240f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
241f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (EXTRA_CHECK) {
242f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Pull the graphic buffer handle back out of the buffer, and confirm
243f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // that it matches expectations.
244f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        OMX_U8* data = header->pBuffer;
245f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        buffer_handle_t bufferHandle;
246f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        memcpy(&bufferHandle, data + 4, sizeof(buffer_handle_t));
247f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (bufferHandle != codecBuffer.mGraphicBuffer->handle) {
248f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            // should never happen
249f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
250f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                    bufferHandle, codecBuffer.mGraphicBuffer->handle);
251f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            CHECK(!"codecBufferEmptied: mismatched buffer");
252f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
253f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
254f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
255f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Find matching entry in our cached copy of the BufferQueue slots.
256f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If we find a match, release that slot.  If we don't, the BufferQueue
257f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // has dropped that GraphicBuffer, and there's nothing for us to release.
258d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    int id = codecBuffer.mBuf;
259d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    if (mBufferSlot[id] != NULL &&
260d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
261d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        ALOGV("cbi %d matches bq slot %d, handle=%p",
262d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                cbi, id, mBufferSlot[id]->handle);
263d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar
264a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (id == mLatestSubmittedBufferId) {
265a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            CHECK_GT(mLatestSubmittedBufferUseCount--, 0);
266a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
267a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            mBufferQueue->releaseBuffer(id, codecBuffer.mFrameNumber,
268a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
269a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
270d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    } else {
271f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
272f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                cbi);
273f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
274f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
275f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Mark the codec buffer as available by clearing the GraphicBuffer ref.
276f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mGraphicBuffer = NULL;
277f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
278f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mNumFramesAvailable) {
279f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Fill this codec buffer.
2800c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        CHECK(!mEndOfStreamSent);
2810c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("buffer freed, %d frames avail (eos=%d)",
2820c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                mNumFramesAvailable, mEndOfStream);
283f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
284f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else if (mEndOfStream) {
285f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No frames available, but EOS is pending, so use this buffer to
286f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // send that.
287f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("buffer freed, EOS pending");
288f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
289a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    } else if (mRepeatBufferDeferred) {
290a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        bool success = repeatLatestSubmittedBuffer_l();
291a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (success) {
292a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            ALOGV("deferred repeatLatestSubmittedBuffer_l SUCCESS");
293a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
294a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            ALOGV("deferred repeatLatestSubmittedBuffer_l FAILURE");
295a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
296a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mRepeatBufferDeferred = false;
297f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
298a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
299f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return;
300f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
301f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
302e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Hubervoid GraphicBufferSource::suspend(bool suspend) {
303e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    Mutex::Autolock autoLock(mMutex);
304e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
305e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (suspend) {
306e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        mSuspended = true;
307e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
308e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        while (mNumFramesAvailable > 0) {
309e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            BufferQueue::BufferItem item;
310e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            status_t err = mBufferQueue->acquireBuffer(&item, 0);
311e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
312e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
313e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                // shouldn't happen.
314e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: frame was not available");
315e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
316e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            } else if (err != OK) {
317e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: acquireBuffer returned err=%d", err);
318e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
319e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            }
320e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
321e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            --mNumFramesAvailable;
322e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
323e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
324e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
325e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
326e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return;
327e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
328e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
329e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended = false;
330a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
331a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
332a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (repeatLatestSubmittedBuffer_l()) {
333a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l SUCCESS");
334a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
335a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            mRepeatBufferDeferred = false;
336a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
337a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l FAILURE");
338a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
339a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
340e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber}
341e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
3420c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFaddenbool GraphicBufferSource::fillCodecBuffer_l() {
343f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mExecuting && mNumFramesAvailable > 0);
3440c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
345e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mSuspended) {
346e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return false;
347e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
348e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
349f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
350f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
351f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No buffers available, bail.
352f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("fillCodecBuffer_l: no codec buffers, avail now %d",
353f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                mNumFramesAvailable);
3540c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
3550c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
356f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3570c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%d",
3580c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mNumFramesAvailable);
3590c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    BufferQueue::BufferItem item;
360656e86250cd68f7f362c50a4bc92a865e9deacbeAndy McFadden    status_t err = mBufferQueue->acquireBuffer(&item, 0);
3610c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
3620c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // shouldn't happen
3630c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: frame was not available");
3640c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
3650c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else if (err != OK) {
3660c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // now what? fake end-of-stream?
3670c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
3680c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
3690c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
370f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3710c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mNumFramesAvailable--;
372f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3730c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // Wait for it to become available.
374d76442421eadfa73f2f3a9e50f6caf65b0dd1ce9Mathias Agopian    err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l");
3750c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err != OK) {
3760c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("failed to wait for buffer fence: %d", err);
3770c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // keep going
3780c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
379f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3800c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // If this is the first time we're seeing this buffer, add it to our
3810c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // slot table.
3820c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (item.mGraphicBuffer != NULL) {
3830c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf);
3840c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mBufferSlot[item.mBuf] = item.mGraphicBuffer;
3850c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
3860c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
387d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    err = submitBuffer_l(item, cbi);
3880c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err != OK) {
3890c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf);
390d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
391d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
3920c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else {
3930c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi);
394a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        setLatestSubmittedBuffer_l(item);
395a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
396a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
397a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    return true;
398a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
399a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
400a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huberbool GraphicBufferSource::repeatLatestSubmittedBuffer_l() {
401a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    CHECK(mExecuting && mNumFramesAvailable == 0);
402a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
403a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mLatestSubmittedBufferId < 0 || mSuspended) {
404a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
405a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
406bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden    if (mBufferSlot[mLatestSubmittedBufferId] == NULL) {
407bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // This can happen if the remote side disconnects, causing
408bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // onBuffersReleased() to NULL out our copy of the slots.  The
409bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // buffer is gone, so we have nothing to show.
410bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        //
411bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // To be on the safe side we try to release the buffer.
412bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        ALOGD("repeatLatestSubmittedBuffer_l: slot was NULL");
413bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        mBufferQueue->releaseBuffer(
414bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                mLatestSubmittedBufferId,
415bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                mLatestSubmittedBufferFrameNum,
416bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                EGL_NO_DISPLAY,
417bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                EGL_NO_SYNC_KHR,
418bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                Fence::NO_FENCE);
419bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        mLatestSubmittedBufferId = -1;
420bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        mLatestSubmittedBufferFrameNum = 0;
421bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        return false;
422bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden    }
423a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
424a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    int cbi = findAvailableCodecBuffer_l();
425a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (cbi < 0) {
426a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        // No buffers available, bail.
427a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        ALOGV("repeatLatestSubmittedBuffer_l: no codec buffers.");
428a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
429a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
430a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
431a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    BufferQueue::BufferItem item;
432a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    item.mBuf = mLatestSubmittedBufferId;
433a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    item.mFrameNumber = mLatestSubmittedBufferFrameNum;
434a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
435a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    status_t err = submitBuffer_l(item, cbi);
436a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
437a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (err != OK) {
438a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
439f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
440f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
441a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    ++mLatestSubmittedBufferUseCount;
442a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
4430c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    return true;
444f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
445f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
446a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Hubervoid GraphicBufferSource::setLatestSubmittedBuffer_l(
447a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        const BufferQueue::BufferItem &item) {
448a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    ALOGV("setLatestSubmittedBuffer_l");
449a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
450a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mLatestSubmittedBufferId >= 0) {
451a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (mLatestSubmittedBufferUseCount == 0) {
452a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            mBufferQueue->releaseBuffer(
453a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    mLatestSubmittedBufferId,
454a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    mLatestSubmittedBufferFrameNum,
455a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    EGL_NO_DISPLAY,
456a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    EGL_NO_SYNC_KHR,
457a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    Fence::NO_FENCE);
458a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
459a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
460a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
461a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferId = item.mBuf;
462a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferFrameNum = item.mFrameNumber;
463a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferUseCount = 1;
464a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred = false;
465a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
466a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mReflector != NULL) {
467a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id());
468a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        msg->setInt32("generation", ++mRepeatLastFrameGeneration);
469a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        msg->post(mRepeatAfterUs);
470a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
471a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
472a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
473ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenstatus_t GraphicBufferSource::signalEndOfInputStream() {
474f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
475ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    ALOGV("signalEndOfInputStream: exec=%d avail=%d eos=%d",
476ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden            mExecuting, mNumFramesAvailable, mEndOfStream);
477ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
478ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    if (mEndOfStream) {
479ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        ALOGE("EOS was already signaled");
480ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        return INVALID_OPERATION;
481ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    }
482f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
483f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Set the end-of-stream flag.  If no frames are pending from the
484f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // BufferQueue, and a codec buffer is available, and we're executing,
485f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // we initiate the EOS from here.  Otherwise, we'll let
486f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // codecBufferEmptied() (or omxExecuting) do it.
487f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //
488f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note: if there are no pending frames and all codec buffers are
489f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // available, we *must* submit the EOS from here or we'll just
490f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // stall since no future events are expected.
491f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream = true;
492f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
493f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting && mNumFramesAvailable == 0) {
494f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
495f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
496ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
497ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    return OK;
498f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
499f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
500d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnarstatus_t GraphicBufferSource::submitBuffer_l(
501d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        const BufferQueue::BufferItem &item, int cbi) {
502f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("submitBuffer_l cbi=%d", cbi);
503f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
504d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf];
505d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mBuf = item.mBuf;
506d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mFrameNumber = item.mFrameNumber;
507f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
508f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
509f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(header->nAllocLen >= 4 + sizeof(buffer_handle_t));
510f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_U8* data = header->pBuffer;
511f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    const OMX_U32 type = kMetadataBufferTypeGrallocSource;
512f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    buffer_handle_t handle = codecBuffer.mGraphicBuffer->handle;
513f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    memcpy(data, &type, 4);
514f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    memcpy(data + 4, &handle, sizeof(buffer_handle_t));
515f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
516f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    status_t err = mNodeInstance->emptyDirectBuffer(header, 0,
517f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME,
518d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar            item.mTimestamp / 1000);
519f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
520f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err);
521f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        codecBuffer.mGraphicBuffer = NULL;
522f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return err;
523f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
524f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
525f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("emptyDirectBuffer succeeded, h=%p p=%p bufhandle=%p",
526f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->pBuffer, handle);
527f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return OK;
528f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
529f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
530f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::submitEndOfInputStream_l() {
531f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mEndOfStream);
532f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStreamSent) {
533f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("EOS already sent");
534f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
535f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
536f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
537f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
538f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
539f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: no codec buffers available");
540f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
541f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
542f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
543f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // We reject any additional incoming graphic buffers, so there's no need
544f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as
545f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // in-use.
546f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
547f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
548f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
549f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (EXTRA_CHECK) {
550f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Guard against implementations that don't check nFilledLen.
551f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        size_t fillLen = 4 + sizeof(buffer_handle_t);
552f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        CHECK(header->nAllocLen >= fillLen);
553f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        OMX_U8* data = header->pBuffer;
554f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        memset(data, 0xcd, fillLen);
555f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
556f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
557f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    uint64_t timestamp = 0; // does this matter?
558f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
559f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    status_t err = mNodeInstance->emptyDirectBuffer(header, /*offset*/ 0,
560f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            /*length*/ 0, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
561f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            timestamp);
562f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
563f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
564f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else {
565f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d",
566f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                header, cbi);
5670c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mEndOfStreamSent = true;
568f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
569f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
570f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
571f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findAvailableCodecBuffer_l() {
572f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mCodecBuffers.size() > 0);
573f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
574f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
575f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mGraphicBuffer == NULL) {
576f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
577f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
578f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
579f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
580f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
581f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
582f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findMatchingCodecBuffer_l(
583f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        const OMX_BUFFERHEADERTYPE* header) {
584f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
585f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mHeader == header) {
586f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
587f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
588f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
589f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
590f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
591f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
592f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
593f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::onFrameAvailable() {
594f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
595f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
5960c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("onFrameAvailable exec=%d avail=%d",
5970c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mExecuting, mNumFramesAvailable);
598f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
599e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mEndOfStream || mSuspended) {
600e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        if (mEndOfStream) {
601e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // This should only be possible if a new buffer was queued after
602e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // EOS was signaled, i.e. the app is misbehaving.
603e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
604e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGW("onFrameAvailable: EOS is set, ignoring frame");
605e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        } else {
606e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGV("onFrameAvailable: suspended, ignoring frame");
607e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
608f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
609f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        BufferQueue::BufferItem item;
610656e86250cd68f7f362c50a4bc92a865e9deacbeAndy McFadden        status_t err = mBufferQueue->acquireBuffer(&item, 0);
611f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (err == OK) {
612d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar            mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
613d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
614f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
615f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
616f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
617f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
618f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable++;
619f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
620a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred = false;
621a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    ++mRepeatLastFrameGeneration;
622a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
623f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
624f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
625f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
626f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
627f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
628f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
629f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::onBuffersReleased() {
630f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock lock(mMutex);
631f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
632f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    uint32_t slotMask;
633f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mBufferQueue->getReleasedBuffers(&slotMask) != NO_ERROR) {
634f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("onBuffersReleased: unable to get released buffer set");
635f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        slotMask = 0xffffffff;
636f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
637f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
638f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("onBuffersReleased: 0x%08x", slotMask);
639f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
640f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
641f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if ((slotMask & 0x01) != 0) {
642f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mBufferSlot[i] = NULL;
643f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
644f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        slotMask >>= 1;
645f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
646f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
647f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
648a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huberstatus_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(
649a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        int64_t repeatAfterUs) {
650a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    Mutex::Autolock autoLock(mMutex);
651a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
652a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mExecuting || repeatAfterUs <= 0ll) {
653a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return INVALID_OPERATION;
654a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
655a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
656a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatAfterUs = repeatAfterUs;
657a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
658a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    return OK;
659a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
660a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
661a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Hubervoid GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
662a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    switch (msg->what()) {
663a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        case kWhatRepeatLastFrame:
664a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        {
665a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            Mutex::Autolock autoLock(mMutex);
666a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
667a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            int32_t generation;
668a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            CHECK(msg->findInt32("generation", &generation));
669a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
670a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (generation != mRepeatLastFrameGeneration) {
671a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                // stale
672a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                break;
673a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
674a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
675a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (!mExecuting || mNumFramesAvailable > 0) {
676a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                break;
677a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
678a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
679a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            bool success = repeatLatestSubmittedBuffer_l();
680a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
681a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (success) {
682a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                ALOGV("repeatLatestSubmittedBuffer_l SUCCESS");
683a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            } else {
684a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                ALOGV("repeatLatestSubmittedBuffer_l FAILURE");
685a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                mRepeatBufferDeferred = true;
686a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
687a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            break;
688a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
689a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
690a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        default:
691a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            TRESPASS();
692a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
693a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
694a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
695f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}  // namespace android
696