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
151ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenvoid GraphicBufferSource::omxLoaded(){
152f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
153ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    if (!mExecuting) {
154ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        // This can happen if something failed very early.
155ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        ALOGW("Dropped back down to Loaded without Executing");
156ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    }
157f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
158a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mLooper != NULL) {
159a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->unregisterHandler(mReflector->id());
160a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mReflector.clear();
161a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
162a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->stop();
163a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper.clear();
164a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
165a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
166ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    ALOGV("--> loaded; avail=%d eos=%d eosSent=%d",
167f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
168f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
169f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Codec is no longer executing.  Discard all codec-related state.
170f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.clear();
171f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
172f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //       are null; complain if not
173f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
174f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = false;
175f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
176f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
177f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) {
178f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
179f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
180f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
181f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen -- buffers can only be allocated when
182f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // transitioning from "loaded" to "idle".
183f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("addCodecBuffer: buffer added while executing");
184f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
185f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
186f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
187f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("addCodecBuffer h=%p size=%lu p=%p",
188f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->pBuffer);
189f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer codecBuffer;
190f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mHeader = header;
191f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.add(codecBuffer);
192f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
193f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
194f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) {
195f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
196f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
197f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mExecuting);  // could this happen if app stop()s early?
198f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
199f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findMatchingCodecBuffer_l(header);
200f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
201f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen.
202f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header);
203f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
204f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
205f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
206f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("codecBufferEmptied h=%p size=%lu filled=%lu p=%p",
207f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->nFilledLen,
208f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header->pBuffer);
209f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
210f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
211f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // header->nFilledLen may not be the original value, so we can't compare
212f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that to zero to see of this was the EOS buffer.  Instead we just
213f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // see if the GraphicBuffer reference was null, which should only ever
214f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // happen for EOS.
215f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (codecBuffer.mGraphicBuffer == NULL) {
2160c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        CHECK(mEndOfStream && mEndOfStreamSent);
217f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No GraphicBuffer to deal with, no additional input or output is
218f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // expected, so just return.
219f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
220f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
221f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
222f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (EXTRA_CHECK) {
223f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Pull the graphic buffer handle back out of the buffer, and confirm
224f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // that it matches expectations.
225f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        OMX_U8* data = header->pBuffer;
226f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        buffer_handle_t bufferHandle;
227f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        memcpy(&bufferHandle, data + 4, sizeof(buffer_handle_t));
228f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (bufferHandle != codecBuffer.mGraphicBuffer->handle) {
229f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            // should never happen
230f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
231f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                    bufferHandle, codecBuffer.mGraphicBuffer->handle);
232f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            CHECK(!"codecBufferEmptied: mismatched buffer");
233f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
234f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
235f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
236f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Find matching entry in our cached copy of the BufferQueue slots.
237f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If we find a match, release that slot.  If we don't, the BufferQueue
238f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // has dropped that GraphicBuffer, and there's nothing for us to release.
239d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    int id = codecBuffer.mBuf;
240d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    if (mBufferSlot[id] != NULL &&
241d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
242d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        ALOGV("cbi %d matches bq slot %d, handle=%p",
243d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                cbi, id, mBufferSlot[id]->handle);
244d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar
245a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (id == mLatestSubmittedBufferId) {
246a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            CHECK_GT(mLatestSubmittedBufferUseCount--, 0);
247a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
248a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            mBufferQueue->releaseBuffer(id, codecBuffer.mFrameNumber,
249a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
250a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
251d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    } else {
252f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
253f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                cbi);
254f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
255f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
256f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Mark the codec buffer as available by clearing the GraphicBuffer ref.
257f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mGraphicBuffer = NULL;
258f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
259f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mNumFramesAvailable) {
260f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Fill this codec buffer.
2610c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        CHECK(!mEndOfStreamSent);
2620c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("buffer freed, %d frames avail (eos=%d)",
2630c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                mNumFramesAvailable, mEndOfStream);
264f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
265f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else if (mEndOfStream) {
266f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No frames available, but EOS is pending, so use this buffer to
267f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // send that.
268f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("buffer freed, EOS pending");
269f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
270a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    } else if (mRepeatBufferDeferred) {
271a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        bool success = repeatLatestSubmittedBuffer_l();
272a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (success) {
273a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            ALOGV("deferred repeatLatestSubmittedBuffer_l SUCCESS");
274a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
275a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            ALOGV("deferred repeatLatestSubmittedBuffer_l FAILURE");
276a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
277a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mRepeatBufferDeferred = false;
278f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
279a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
280f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return;
281f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
282f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
283e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Hubervoid GraphicBufferSource::suspend(bool suspend) {
284e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    Mutex::Autolock autoLock(mMutex);
285e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
286e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (suspend) {
287e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        mSuspended = true;
288e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
289e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        while (mNumFramesAvailable > 0) {
290e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            BufferQueue::BufferItem item;
291e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            status_t err = mBufferQueue->acquireBuffer(&item, 0);
292e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
293e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
294e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                // shouldn't happen.
295e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: frame was not available");
296e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
297e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            } else if (err != OK) {
298e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: acquireBuffer returned err=%d", err);
299e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
300e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            }
301e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
302e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            --mNumFramesAvailable;
303e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
304e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
305e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
306e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
307e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return;
308e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
309e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
310e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended = false;
311a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
312a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
313a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (repeatLatestSubmittedBuffer_l()) {
314a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l SUCCESS");
315a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
316a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            mRepeatBufferDeferred = false;
317a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
318a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l FAILURE");
319a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
320a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
321e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber}
322e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
3230c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFaddenbool GraphicBufferSource::fillCodecBuffer_l() {
324f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mExecuting && mNumFramesAvailable > 0);
3250c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
326e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mSuspended) {
327e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return false;
328e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
329e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
330f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
331f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
332f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No buffers available, bail.
333f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("fillCodecBuffer_l: no codec buffers, avail now %d",
334f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                mNumFramesAvailable);
3350c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
3360c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
337f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3380c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%d",
3390c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mNumFramesAvailable);
3400c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    BufferQueue::BufferItem item;
341656e86250cd68f7f362c50a4bc92a865e9deacbeAndy McFadden    status_t err = mBufferQueue->acquireBuffer(&item, 0);
3420c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
3430c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // shouldn't happen
3440c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: frame was not available");
3450c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
3460c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else if (err != OK) {
3470c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // now what? fake end-of-stream?
3480c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
3490c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
3500c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
351f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3520c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mNumFramesAvailable--;
353f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3540c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // Wait for it to become available.
355d76442421eadfa73f2f3a9e50f6caf65b0dd1ce9Mathias Agopian    err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l");
3560c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err != OK) {
3570c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("failed to wait for buffer fence: %d", err);
3580c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // keep going
3590c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
360f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
3610c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // If this is the first time we're seeing this buffer, add it to our
3620c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // slot table.
3630c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (item.mGraphicBuffer != NULL) {
3640c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf);
3650c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mBufferSlot[item.mBuf] = item.mGraphicBuffer;
3660c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
3670c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
368d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    err = submitBuffer_l(item, cbi);
3690c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err != OK) {
3700c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf);
371d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
372d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
3730c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else {
3740c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi);
375a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        setLatestSubmittedBuffer_l(item);
376a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
377a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
378a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    return true;
379a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
380a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
381a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huberbool GraphicBufferSource::repeatLatestSubmittedBuffer_l() {
382a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    CHECK(mExecuting && mNumFramesAvailable == 0);
383a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
384a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mLatestSubmittedBufferId < 0 || mSuspended) {
385a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
386a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
387a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
388a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    int cbi = findAvailableCodecBuffer_l();
389a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (cbi < 0) {
390a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        // No buffers available, bail.
391a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        ALOGV("repeatLatestSubmittedBuffer_l: no codec buffers.");
392a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
393a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
394a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
395a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    BufferQueue::BufferItem item;
396a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    item.mBuf = mLatestSubmittedBufferId;
397a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    item.mFrameNumber = mLatestSubmittedBufferFrameNum;
398a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
399a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    status_t err = submitBuffer_l(item, cbi);
400a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
401a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (err != OK) {
402a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
403f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
404f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
405a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    ++mLatestSubmittedBufferUseCount;
406a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
4070c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    return true;
408f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
409f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
410a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Hubervoid GraphicBufferSource::setLatestSubmittedBuffer_l(
411a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        const BufferQueue::BufferItem &item) {
412a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    ALOGV("setLatestSubmittedBuffer_l");
413a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
414a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mLatestSubmittedBufferId >= 0) {
415a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (mLatestSubmittedBufferUseCount == 0) {
416a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            mBufferQueue->releaseBuffer(
417a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    mLatestSubmittedBufferId,
418a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    mLatestSubmittedBufferFrameNum,
419a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    EGL_NO_DISPLAY,
420a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    EGL_NO_SYNC_KHR,
421a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                    Fence::NO_FENCE);
422a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
423a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
424a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
425a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferId = item.mBuf;
426a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferFrameNum = item.mFrameNumber;
427a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mLatestSubmittedBufferUseCount = 1;
428a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred = false;
429a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
430a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mReflector != NULL) {
431a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id());
432a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        msg->setInt32("generation", ++mRepeatLastFrameGeneration);
433a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        msg->post(mRepeatAfterUs);
434a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
435a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
436a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
437ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenstatus_t GraphicBufferSource::signalEndOfInputStream() {
438f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
439ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    ALOGV("signalEndOfInputStream: exec=%d avail=%d eos=%d",
440ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden            mExecuting, mNumFramesAvailable, mEndOfStream);
441ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
442ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    if (mEndOfStream) {
443ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        ALOGE("EOS was already signaled");
444ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        return INVALID_OPERATION;
445ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    }
446f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
447f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Set the end-of-stream flag.  If no frames are pending from the
448f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // BufferQueue, and a codec buffer is available, and we're executing,
449f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // we initiate the EOS from here.  Otherwise, we'll let
450f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // codecBufferEmptied() (or omxExecuting) do it.
451f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //
452f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note: if there are no pending frames and all codec buffers are
453f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // available, we *must* submit the EOS from here or we'll just
454f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // stall since no future events are expected.
455f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream = true;
456f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
457f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting && mNumFramesAvailable == 0) {
458f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
459f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
460ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
461ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    return OK;
462f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
463f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
464d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnarstatus_t GraphicBufferSource::submitBuffer_l(
465d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        const BufferQueue::BufferItem &item, int cbi) {
466f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("submitBuffer_l cbi=%d", cbi);
467f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
468d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf];
469d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mBuf = item.mBuf;
470d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mFrameNumber = item.mFrameNumber;
471f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
472f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
473f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(header->nAllocLen >= 4 + sizeof(buffer_handle_t));
474f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_U8* data = header->pBuffer;
475f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    const OMX_U32 type = kMetadataBufferTypeGrallocSource;
476f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    buffer_handle_t handle = codecBuffer.mGraphicBuffer->handle;
477f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    memcpy(data, &type, 4);
478f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    memcpy(data + 4, &handle, sizeof(buffer_handle_t));
479f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
480f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    status_t err = mNodeInstance->emptyDirectBuffer(header, 0,
481f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME,
482d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar            item.mTimestamp / 1000);
483f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
484f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err);
485f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        codecBuffer.mGraphicBuffer = NULL;
486f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return err;
487f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
488f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
489f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("emptyDirectBuffer succeeded, h=%p p=%p bufhandle=%p",
490f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->pBuffer, handle);
491f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return OK;
492f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
493f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
494f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::submitEndOfInputStream_l() {
495f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mEndOfStream);
496f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStreamSent) {
497f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("EOS already sent");
498f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
499f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
500f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
501f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
502f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
503f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: no codec buffers available");
504f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
505f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
506f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
507f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // We reject any additional incoming graphic buffers, so there's no need
508f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as
509f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // in-use.
510f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
511f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
512f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
513f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (EXTRA_CHECK) {
514f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Guard against implementations that don't check nFilledLen.
515f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        size_t fillLen = 4 + sizeof(buffer_handle_t);
516f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        CHECK(header->nAllocLen >= fillLen);
517f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        OMX_U8* data = header->pBuffer;
518f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        memset(data, 0xcd, fillLen);
519f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
520f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
521f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    uint64_t timestamp = 0; // does this matter?
522f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
523f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    status_t err = mNodeInstance->emptyDirectBuffer(header, /*offset*/ 0,
524f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            /*length*/ 0, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
525f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            timestamp);
526f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
527f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
528f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else {
529f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d",
530f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                header, cbi);
5310c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mEndOfStreamSent = true;
532f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
533f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
534f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
535f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findAvailableCodecBuffer_l() {
536f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mCodecBuffers.size() > 0);
537f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
538f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
539f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mGraphicBuffer == NULL) {
540f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
541f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
542f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
543f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
544f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
545f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
546f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findMatchingCodecBuffer_l(
547f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        const OMX_BUFFERHEADERTYPE* header) {
548f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
549f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mHeader == header) {
550f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
551f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
552f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
553f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
554f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
555f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
556f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
557f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::onFrameAvailable() {
558f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
559f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
5600c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("onFrameAvailable exec=%d avail=%d",
5610c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mExecuting, mNumFramesAvailable);
562f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
563e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mEndOfStream || mSuspended) {
564e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        if (mEndOfStream) {
565e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // This should only be possible if a new buffer was queued after
566e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // EOS was signaled, i.e. the app is misbehaving.
567e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
568e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGW("onFrameAvailable: EOS is set, ignoring frame");
569e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        } else {
570e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGV("onFrameAvailable: suspended, ignoring frame");
571e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
572f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
573f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        BufferQueue::BufferItem item;
574656e86250cd68f7f362c50a4bc92a865e9deacbeAndy McFadden        status_t err = mBufferQueue->acquireBuffer(&item, 0);
575f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (err == OK) {
576d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar            mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
577d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
578f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
579f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
580f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
581f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
582f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable++;
583f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
584a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred = false;
585a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    ++mRepeatLastFrameGeneration;
586a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
587f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
588f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
589f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
590f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
591f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
592f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
593f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::onBuffersReleased() {
594f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock lock(mMutex);
595f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
596f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    uint32_t slotMask;
597f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mBufferQueue->getReleasedBuffers(&slotMask) != NO_ERROR) {
598f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("onBuffersReleased: unable to get released buffer set");
599f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        slotMask = 0xffffffff;
600f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
601f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
602f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("onBuffersReleased: 0x%08x", slotMask);
603f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
604f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
605f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if ((slotMask & 0x01) != 0) {
606f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mBufferSlot[i] = NULL;
607f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
608f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        slotMask >>= 1;
609f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
610f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
611f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
612a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huberstatus_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(
613a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        int64_t repeatAfterUs) {
614a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    Mutex::Autolock autoLock(mMutex);
615a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
616a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mExecuting || repeatAfterUs <= 0ll) {
617a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return INVALID_OPERATION;
618a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
619a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
620a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatAfterUs = repeatAfterUs;
621a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
622a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    return OK;
623a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
624a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
625a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Hubervoid GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
626a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    switch (msg->what()) {
627a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        case kWhatRepeatLastFrame:
628a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        {
629a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            Mutex::Autolock autoLock(mMutex);
630a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
631a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            int32_t generation;
632a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            CHECK(msg->findInt32("generation", &generation));
633a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
634a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (generation != mRepeatLastFrameGeneration) {
635a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                // stale
636a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                break;
637a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
638a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
639a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (!mExecuting || mNumFramesAvailable > 0) {
640a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                break;
641a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
642a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
643a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            bool success = repeatLatestSubmittedBuffer_l();
644a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
645a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (success) {
646a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                ALOGV("repeatLatestSubmittedBuffer_l SUCCESS");
647a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            } else {
648a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                ALOGV("repeatLatestSubmittedBuffer_l FAILURE");
649a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                mRepeatBufferDeferred = true;
650a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
651a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            break;
652a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
653a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
654a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        default:
655a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            TRESPASS();
656a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
657a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
658a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
659f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}  // namespace android
660