GraphicBufferSource.cpp revision 15ab4996019387f27a48b81cb4774c21502bc0e5
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
17db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn#include <inttypes.h>
18db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn
19f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#define LOG_TAG "GraphicBufferSource"
20ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden//#define LOG_NDEBUG 0
21f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <utils/Log.h>
22f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
235e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian#include "GraphicBufferSource.h"
24f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
25f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <OMX_Core.h>
26f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <media/stagefright/foundation/ADebug.h>
27a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber#include <media/stagefright/foundation/AMessage.h>
28f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
295e1f08b3917ac7900f8a11118afb7e8bf3e61c64Mathias Agopian#include <media/hardware/MetadataBufferType.h>
30f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden#include <ui/GraphicBuffer.h>
318ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza#include <gui/BufferItem.h>
32054219874873b41f1c815552987c10465c34ba2bLajos Molnar#include <HardwareAPI.h>
33f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
342475264264b51a7592c5b2e4cd6cfdaddba16644Dan Stoza#include <inttypes.h>
3537b2b389139ed638831e49708c947863eef631efRonghua Wu#include "FrameDropper.h"
362475264264b51a7592c5b2e4cd6cfdaddba16644Dan Stoza
37f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddennamespace android {
38f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
39f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenstatic const bool EXTRA_CHECK = true;
40f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
41f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
42d291c222357303b9611cab89d0c3b047584ef377Chong ZhangGraphicBufferSource::GraphicBufferSource(
43d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        OMXNodeInstance* nodeInstance,
44d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        uint32_t bufferWidth,
45d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        uint32_t bufferHeight,
46d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        uint32_t bufferCount,
47d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        const sp<IGraphicBufferConsumer> &consumer) :
48f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mInitCheck(UNKNOWN_ERROR),
49f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNodeInstance(nodeInstance),
50f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting(false),
51e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended(false),
52d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    mIsPersistent(false),
53d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    mConsumer(consumer),
54f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable(0),
55f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream(false),
56a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mEndOfStreamSent(false),
5794ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mMaxTimestampGapUs(-1ll),
5894ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mPrevOriginalTimeUs(-1ll),
5994ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mPrevModifiedTimeUs(-1ll),
6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSkipFramesBeforeNs(-1ll),
6184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    mRepeatAfterUs(-1ll),
62a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatLastFrameGeneration(0),
6394ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mRepeatLastFrameTimestamp(-1ll),
6437b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferId(-1),
6537b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferFrameNum(0),
6637b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferUseCount(0),
6715ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar    mLatestBufferFence(Fence::NO_FENCE),
682c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mRepeatBufferDeferred(false),
692c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mTimePerCaptureUs(-1ll),
702c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mTimePerFrameUs(-1ll),
712c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mPrevCaptureUs(-1ll),
72054219874873b41f1c815552987c10465c34ba2bLajos Molnar    mPrevFrameUs(-1ll) {
73f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
740c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("GraphicBufferSource w=%u h=%u c=%u",
750c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            bufferWidth, bufferHeight, bufferCount);
76f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
77f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (bufferWidth == 0 || bufferHeight == 0) {
780c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
79f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        mInitCheck = BAD_VALUE;
80f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
81f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
82f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
83d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    if (mConsumer == NULL) {
84d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        String8 name("GraphicBufferSource");
850c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
86d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
87d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        mConsumer->setConsumerName(name);
88d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
89d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
90d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        if (mInitCheck != NO_ERROR) {
91d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
92d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                    bufferCount, mInitCheck);
93d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            return;
94d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        }
95d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    } else {
96d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        mIsPersistent = true;
970c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
98d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
99f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
100f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // reference once the ctor ends, as that would cause the refcount of 'this'
101f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
102f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that's what we create.
103910813bd66eaf0f6a72769c9b3fa9830dd100a19Mathias Agopian    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
104910813bd66eaf0f6a72769c9b3fa9830dd100a19Mathias Agopian    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
105f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
1065205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza    mInitCheck = mConsumer->consumerConnect(proxy, false);
1070c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (mInitCheck != NO_ERROR) {
108f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("Error connecting to BufferQueue: %s (%d)",
1090c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                strerror(-mInitCheck), mInitCheck);
110f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
111f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
112f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
1130c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    CHECK(mInitCheck == NO_ERROR);
114f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
115f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
116f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenGraphicBufferSource::~GraphicBufferSource() {
117f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("~GraphicBufferSource");
118d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    if (mConsumer != NULL && !mIsPersistent) {
1195205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza        status_t err = mConsumer->consumerDisconnect();
1200c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        if (err != NO_ERROR) {
1210c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            ALOGW("consumerDisconnect failed: %d", err);
1220c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        }
123f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
124f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
125f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
126f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::omxExecuting() {
127f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
128a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("--> executing; avail=%zu, codec vec size=%zd",
129f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mCodecBuffers.size());
130f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(!mExecuting);
131f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = true;
132f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
133f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Start by loading up as many buffers as possible.  We want to do this,
134f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // rather than just submit the first buffer, to avoid a degenerate case:
135f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // if all BQ buffers arrive before we start executing, and we only submit
136f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // one here, the other BQ buffers will just sit until we get notified
137f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that the codec buffer has been released.  We'd then acquire and
138f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // submit a single additional buffer, repeatedly, never using more than
139f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // one codec buffer simultaneously.  (We could instead try to submit
140f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // all BQ buffers whenever any codec buffer is freed, but if we get the
141f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // initial conditions right that will never be useful.)
1420c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    while (mNumFramesAvailable) {
1430c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        if (!fillCodecBuffer_l()) {
1440c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            ALOGV("stop load with frames available (codecAvail=%d)",
1450c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                    isCodecBufferAvailable_l());
1460c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            break;
1470c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        }
148f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
149f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
150a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("done loading initial frames, avail=%zu", mNumFramesAvailable);
151f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
152f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If EOS has already been signaled, and there are no more frames to
153f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // submit, try to send EOS now as well.
154f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStream && mNumFramesAvailable == 0) {
155f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
156f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
157a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
158a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mRepeatAfterUs > 0ll && mLooper == NULL) {
159a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mReflector = new AHandlerReflector<GraphicBufferSource>(this);
160a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
161a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper = new ALooper;
162a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->registerHandler(mReflector);
163a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->start();
164a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
16537b2b389139ed638831e49708c947863eef631efRonghua Wu        if (mLatestBufferId >= 0) {
166a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            sp<AMessage> msg =
1671d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                new AMessage(kWhatRepeatLastFrame, mReflector);
168a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
169a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            msg->setInt32("generation", ++mRepeatLastFrameGeneration);
170a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            msg->post(mRepeatAfterUs);
171a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
172a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
173f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
174f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
175ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Hubervoid GraphicBufferSource::omxIdle() {
176ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    ALOGV("omxIdle");
177ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
178ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    Mutex::Autolock autoLock(mMutex);
179ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
180ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    if (mExecuting) {
181ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber        // We are only interested in the transition from executing->idle,
182ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber        // not loaded->idle.
183892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber        mExecuting = false;
184ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    }
185ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber}
186ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
187ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenvoid GraphicBufferSource::omxLoaded(){
188f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
189ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    if (!mExecuting) {
190ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        // This can happen if something failed very early.
191ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        ALOGW("Dropped back down to Loaded without Executing");
192ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    }
193f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
194a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mLooper != NULL) {
195a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->unregisterHandler(mReflector->id());
196a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mReflector.clear();
197a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
198a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->stop();
199a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper.clear();
200a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
201a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
202a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d",
203f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
204f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
205f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Codec is no longer executing.  Discard all codec-related state.
206f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.clear();
207f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
208f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //       are null; complain if not
209f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
210f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = false;
211f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
212f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
213f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) {
214f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
215f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
216f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
217f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen -- buffers can only be allocated when
218f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // transitioning from "loaded" to "idle".
219f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("addCodecBuffer: buffer added while executing");
220f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
221f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
222f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
223db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn    ALOGV("addCodecBuffer h=%p size=%" PRIu32 " p=%p",
224f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->pBuffer);
225f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer codecBuffer;
226f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mHeader = header;
227f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.add(codecBuffer);
228f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
229f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
23015ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnarvoid GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header, int fenceFd) {
231f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
232892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber    if (!mExecuting) {
233892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber        return;
234892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber    }
235f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
236f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findMatchingCodecBuffer_l(header);
237f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
238f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen.
239f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header);
24015ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        if (fenceFd >= 0) {
24115ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            ::close(fenceFd);
24215ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        }
243f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
244f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
245f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
246db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn    ALOGV("codecBufferEmptied h=%p size=%" PRIu32 " filled=%" PRIu32 " p=%p",
247f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->nFilledLen,
248f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header->pBuffer);
249f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
250f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
251f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // header->nFilledLen may not be the original value, so we can't compare
252f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that to zero to see of this was the EOS buffer.  Instead we just
253f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // see if the GraphicBuffer reference was null, which should only ever
254f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // happen for EOS.
255f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (codecBuffer.mGraphicBuffer == NULL) {
2565572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden        if (!(mEndOfStream && mEndOfStreamSent)) {
2575572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            // This can happen when broken code sends us the same buffer
2585572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            // twice in a row.
2595572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            ALOGE("ERROR: codecBufferEmptied on non-EOS null buffer "
2605572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden                    "(buffer emptied twice?)");
2615572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden        }
262f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No GraphicBuffer to deal with, no additional input or output is
263f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // expected, so just return.
26415ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        if (fenceFd >= 0) {
26515ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            ::close(fenceFd);
26615ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        }
267f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
268f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
269f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
270054219874873b41f1c815552987c10465c34ba2bLajos Molnar    if (EXTRA_CHECK && header->nAllocLen >= sizeof(MetadataBufferType)) {
271f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Pull the graphic buffer handle back out of the buffer, and confirm
272f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // that it matches expectations.
273f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        OMX_U8* data = header->pBuffer;
274512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar        MetadataBufferType type = *(MetadataBufferType *)data;
275054219874873b41f1c815552987c10465c34ba2bLajos Molnar        if (type == kMetadataBufferTypeGrallocSource
276054219874873b41f1c815552987c10465c34ba2bLajos Molnar                && header->nAllocLen >= sizeof(VideoGrallocMetadata)) {
277054219874873b41f1c815552987c10465c34ba2bLajos Molnar            VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)data;
278054219874873b41f1c815552987c10465c34ba2bLajos Molnar            if (grallocMeta.hHandle != codecBuffer.mGraphicBuffer->handle) {
279512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                // should never happen
280512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
281054219874873b41f1c815552987c10465c34ba2bLajos Molnar                        grallocMeta.hHandle, codecBuffer.mGraphicBuffer->handle);
282512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                CHECK(!"codecBufferEmptied: mismatched buffer");
283512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar            }
284054219874873b41f1c815552987c10465c34ba2bLajos Molnar        } else if (type == kMetadataBufferTypeANWBuffer
285054219874873b41f1c815552987c10465c34ba2bLajos Molnar                && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
286054219874873b41f1c815552987c10465c34ba2bLajos Molnar            VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)data;
287054219874873b41f1c815552987c10465c34ba2bLajos Molnar            if (nativeMeta.pBuffer != codecBuffer.mGraphicBuffer->getNativeBuffer()) {
288512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                // should never happen
289512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                ALOGE("codecBufferEmptied: buffer is %p, expected %p",
290054219874873b41f1c815552987c10465c34ba2bLajos Molnar                        nativeMeta.pBuffer, codecBuffer.mGraphicBuffer->getNativeBuffer());
291512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                CHECK(!"codecBufferEmptied: mismatched buffer");
292512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar            }
293f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
294f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
295f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
296f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Find matching entry in our cached copy of the BufferQueue slots.
297f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If we find a match, release that slot.  If we don't, the BufferQueue
298f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // has dropped that GraphicBuffer, and there's nothing for us to release.
299d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    int id = codecBuffer.mBuf;
30015ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar    sp<Fence> fence = new Fence(fenceFd);
301d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    if (mBufferSlot[id] != NULL &&
302d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
303d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        ALOGV("cbi %d matches bq slot %d, handle=%p",
304d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                cbi, id, mBufferSlot[id]->handle);
305d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar
30637b2b389139ed638831e49708c947863eef631efRonghua Wu        if (id == mLatestBufferId) {
30737b2b389139ed638831e49708c947863eef631efRonghua Wu            CHECK_GT(mLatestBufferUseCount--, 0);
308a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
309d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            if (mIsPersistent) {
310d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->detachBuffer(id);
311d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                int outSlot;
312d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->attachBuffer(&outSlot, mBufferSlot[id]);
313d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->releaseBuffer(outSlot, 0,
31415ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
315d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            } else {
316d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->releaseBuffer(id, codecBuffer.mFrameNumber,
31715ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
318d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            }
319a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
320d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    } else {
321f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
322f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                cbi);
32315ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        // we will not reuse codec buffer, so there is no need to wait for fence
324f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
325f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
326f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Mark the codec buffer as available by clearing the GraphicBuffer ref.
327f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mGraphicBuffer = NULL;
328f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
329f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mNumFramesAvailable) {
330f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Fill this codec buffer.
3310c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        CHECK(!mEndOfStreamSent);
332a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("buffer freed, %zu frames avail (eos=%d)",
3330c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                mNumFramesAvailable, mEndOfStream);
334f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
335f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else if (mEndOfStream) {
336f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No frames available, but EOS is pending, so use this buffer to
337f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // send that.
338f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("buffer freed, EOS pending");
339f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
340a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    } else if (mRepeatBufferDeferred) {
34137b2b389139ed638831e49708c947863eef631efRonghua Wu        bool success = repeatLatestBuffer_l();
342a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (success) {
34337b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("deferred repeatLatestBuffer_l SUCCESS");
344a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
34537b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("deferred repeatLatestBuffer_l FAILURE");
346a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
347a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mRepeatBufferDeferred = false;
348f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
349a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
350f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return;
351f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
352f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
35394ee4b708acfa941581160b267afb79192b1d816Chong Zhangvoid GraphicBufferSource::codecBufferFilled(OMX_BUFFERHEADERTYPE* header) {
35494ee4b708acfa941581160b267afb79192b1d816Chong Zhang    Mutex::Autolock autoLock(mMutex);
35594ee4b708acfa941581160b267afb79192b1d816Chong Zhang
35694ee4b708acfa941581160b267afb79192b1d816Chong Zhang    if (mMaxTimestampGapUs > 0ll
35794ee4b708acfa941581160b267afb79192b1d816Chong Zhang            && !(header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
35894ee4b708acfa941581160b267afb79192b1d816Chong Zhang        ssize_t index = mOriginalTimeUs.indexOfKey(header->nTimeStamp);
35994ee4b708acfa941581160b267afb79192b1d816Chong Zhang        if (index >= 0) {
36094ee4b708acfa941581160b267afb79192b1d816Chong Zhang            ALOGV("OUT timestamp: %lld -> %lld",
361a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                    static_cast<long long>(header->nTimeStamp),
362a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                    static_cast<long long>(mOriginalTimeUs[index]));
36394ee4b708acfa941581160b267afb79192b1d816Chong Zhang            header->nTimeStamp = mOriginalTimeUs[index];
36494ee4b708acfa941581160b267afb79192b1d816Chong Zhang            mOriginalTimeUs.removeItemsAt(index);
36594ee4b708acfa941581160b267afb79192b1d816Chong Zhang        } else {
36694ee4b708acfa941581160b267afb79192b1d816Chong Zhang            // giving up the effort as encoder doesn't appear to preserve pts
36794ee4b708acfa941581160b267afb79192b1d816Chong Zhang            ALOGW("giving up limiting timestamp gap (pts = %lld)",
36894ee4b708acfa941581160b267afb79192b1d816Chong Zhang                    header->nTimeStamp);
36994ee4b708acfa941581160b267afb79192b1d816Chong Zhang            mMaxTimestampGapUs = -1ll;
37094ee4b708acfa941581160b267afb79192b1d816Chong Zhang        }
37194ee4b708acfa941581160b267afb79192b1d816Chong Zhang        if (mOriginalTimeUs.size() > BufferQueue::NUM_BUFFER_SLOTS) {
37294ee4b708acfa941581160b267afb79192b1d816Chong Zhang            // something terribly wrong must have happened, giving up...
373a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGE("mOriginalTimeUs has too many entries (%zu)",
37494ee4b708acfa941581160b267afb79192b1d816Chong Zhang                    mOriginalTimeUs.size());
37594ee4b708acfa941581160b267afb79192b1d816Chong Zhang            mMaxTimestampGapUs = -1ll;
37694ee4b708acfa941581160b267afb79192b1d816Chong Zhang        }
37794ee4b708acfa941581160b267afb79192b1d816Chong Zhang    }
37894ee4b708acfa941581160b267afb79192b1d816Chong Zhang}
37994ee4b708acfa941581160b267afb79192b1d816Chong Zhang
380e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Hubervoid GraphicBufferSource::suspend(bool suspend) {
381e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    Mutex::Autolock autoLock(mMutex);
382e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
383e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (suspend) {
384e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        mSuspended = true;
385e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
386e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        while (mNumFramesAvailable > 0) {
3878ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza            BufferItem item;
3885205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza            status_t err = mConsumer->acquireBuffer(&item, 0);
389e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
390e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
391e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                // shouldn't happen.
392e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: frame was not available");
393e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
394e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            } else if (err != OK) {
395e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: acquireBuffer returned err=%d", err);
396e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
397e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            }
398e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
399e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            --mNumFramesAvailable;
400e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
401d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            if (mIsPersistent) {
402d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->detachBuffer(item.mBuf);
403d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer);
404d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->releaseBuffer(item.mBuf, 0,
40515ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
406d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            } else {
407d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
408d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
409d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            }
410e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
411e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return;
412e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
413e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
414e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended = false;
415a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
416a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
41737b2b389139ed638831e49708c947863eef631efRonghua Wu        if (repeatLatestBuffer_l()) {
41837b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
419a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
420a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            mRepeatBufferDeferred = false;
421a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
42237b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
423a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
424a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
425e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber}
426e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
4270c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFaddenbool GraphicBufferSource::fillCodecBuffer_l() {
428f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mExecuting && mNumFramesAvailable > 0);
4290c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
430e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mSuspended) {
431e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return false;
432e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
433e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
434f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
435f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
436f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No buffers available, bail.
437a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("fillCodecBuffer_l: no codec buffers, avail now %zu",
438f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                mNumFramesAvailable);
4390c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
4400c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
441f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
442a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
4430c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mNumFramesAvailable);
4448ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza    BufferItem item;
4455205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza    status_t err = mConsumer->acquireBuffer(&item, 0);
4460c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
4470c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // shouldn't happen
4480c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: frame was not available");
4490c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
4500c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else if (err != OK) {
4510c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // now what? fake end-of-stream?
4520c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
4530c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
4540c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
455f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
4560c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mNumFramesAvailable--;
457f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
4580c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // If this is the first time we're seeing this buffer, add it to our
4590c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // slot table.
4600c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (item.mGraphicBuffer != NULL) {
4610c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf);
4620c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mBufferSlot[item.mBuf] = item.mGraphicBuffer;
4630c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
4640c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    err = UNKNOWN_ERROR;
46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    // only submit sample if start time is unspecified, or sample
46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    // is queued after the specified start time
46937b2b389139ed638831e49708c947863eef631efRonghua Wu    bool dropped = false;
47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) {
47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if start time is set, offset time stamp by start time
47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mSkipFramesBeforeNs > 0) {
47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            item.mTimestamp -= mSkipFramesBeforeNs;
47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
47537b2b389139ed638831e49708c947863eef631efRonghua Wu
47637b2b389139ed638831e49708c947863eef631efRonghua Wu        int64_t timeUs = item.mTimestamp / 1000;
47737b2b389139ed638831e49708c947863eef631efRonghua Wu        if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) {
47837b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs));
47937b2b389139ed638831e49708c947863eef631efRonghua Wu            // set err to OK so that the skipped frame can still be saved as the lastest frame
48037b2b389139ed638831e49708c947863eef631efRonghua Wu            err = OK;
48137b2b389139ed638831e49708c947863eef631efRonghua Wu            dropped = true;
48237b2b389139ed638831e49708c947863eef631efRonghua Wu        } else {
48337b2b389139ed638831e49708c947863eef631efRonghua Wu            err = submitBuffer_l(item, cbi);
48437b2b389139ed638831e49708c947863eef631efRonghua Wu        }
48572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4870c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err != OK) {
4880c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf);
489d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        if (mIsPersistent) {
490d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            mConsumer->detachBuffer(item.mBuf);
491d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer);
492d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            mConsumer->releaseBuffer(item.mBuf, 0,
49315ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
494d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        } else {
495d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
49615ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
497d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        }
49815ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        // item.mFence is released at the end of this method
4990c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else {
5000c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi);
50137b2b389139ed638831e49708c947863eef631efRonghua Wu        setLatestBuffer_l(item, dropped);
502a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
503a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
504a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    return true;
505a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
506a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
50737b2b389139ed638831e49708c947863eef631efRonghua Wubool GraphicBufferSource::repeatLatestBuffer_l() {
508a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    CHECK(mExecuting && mNumFramesAvailable == 0);
509a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
51037b2b389139ed638831e49708c947863eef631efRonghua Wu    if (mLatestBufferId < 0 || mSuspended) {
511a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
512a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
51337b2b389139ed638831e49708c947863eef631efRonghua Wu    if (mBufferSlot[mLatestBufferId] == NULL) {
514bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // This can happen if the remote side disconnects, causing
515bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // onBuffersReleased() to NULL out our copy of the slots.  The
516bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // buffer is gone, so we have nothing to show.
517bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        //
518bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // To be on the safe side we try to release the buffer.
51937b2b389139ed638831e49708c947863eef631efRonghua Wu        ALOGD("repeatLatestBuffer_l: slot was NULL");
5205205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza        mConsumer->releaseBuffer(
52137b2b389139ed638831e49708c947863eef631efRonghua Wu                mLatestBufferId,
52237b2b389139ed638831e49708c947863eef631efRonghua Wu                mLatestBufferFrameNum,
523bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                EGL_NO_DISPLAY,
524bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                EGL_NO_SYNC_KHR,
52515ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                mLatestBufferFence);
52637b2b389139ed638831e49708c947863eef631efRonghua Wu        mLatestBufferId = -1;
52737b2b389139ed638831e49708c947863eef631efRonghua Wu        mLatestBufferFrameNum = 0;
52815ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        mLatestBufferFence = Fence::NO_FENCE;
529bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        return false;
530bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden    }
531a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
532a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    int cbi = findAvailableCodecBuffer_l();
533a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (cbi < 0) {
534a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        // No buffers available, bail.
53537b2b389139ed638831e49708c947863eef631efRonghua Wu        ALOGV("repeatLatestBuffer_l: no codec buffers.");
536a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
537a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
538a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
5398ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza    BufferItem item;
54037b2b389139ed638831e49708c947863eef631efRonghua Wu    item.mBuf = mLatestBufferId;
54137b2b389139ed638831e49708c947863eef631efRonghua Wu    item.mFrameNumber = mLatestBufferFrameNum;
54294ee4b708acfa941581160b267afb79192b1d816Chong Zhang    item.mTimestamp = mRepeatLastFrameTimestamp;
54315ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar    item.mFence = mLatestBufferFence;
544a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
545a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    status_t err = submitBuffer_l(item, cbi);
546a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
547a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (err != OK) {
548a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
549f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
550f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
55137b2b389139ed638831e49708c947863eef631efRonghua Wu    ++mLatestBufferUseCount;
552a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
55394ee4b708acfa941581160b267afb79192b1d816Chong Zhang    /* repeat last frame up to kRepeatLastFrameCount times.
55494ee4b708acfa941581160b267afb79192b1d816Chong Zhang     * in case of static scene, a single repeat might not get rid of encoder
55594ee4b708acfa941581160b267afb79192b1d816Chong Zhang     * ghosting completely, refresh a couple more times to get better quality
55694ee4b708acfa941581160b267afb79192b1d816Chong Zhang     */
55794ee4b708acfa941581160b267afb79192b1d816Chong Zhang    if (--mRepeatLastFrameCount > 0) {
55894ee4b708acfa941581160b267afb79192b1d816Chong Zhang        mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
55994ee4b708acfa941581160b267afb79192b1d816Chong Zhang
56094ee4b708acfa941581160b267afb79192b1d816Chong Zhang        if (mReflector != NULL) {
5611d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
56294ee4b708acfa941581160b267afb79192b1d816Chong Zhang            msg->setInt32("generation", ++mRepeatLastFrameGeneration);
56394ee4b708acfa941581160b267afb79192b1d816Chong Zhang            msg->post(mRepeatAfterUs);
56494ee4b708acfa941581160b267afb79192b1d816Chong Zhang        }
56594ee4b708acfa941581160b267afb79192b1d816Chong Zhang    }
56694ee4b708acfa941581160b267afb79192b1d816Chong Zhang
5670c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    return true;
568f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
569f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
57037b2b389139ed638831e49708c947863eef631efRonghua Wuvoid GraphicBufferSource::setLatestBuffer_l(
5718ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza        const BufferItem &item, bool dropped) {
57237b2b389139ed638831e49708c947863eef631efRonghua Wu    ALOGV("setLatestBuffer_l");
573a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
57437b2b389139ed638831e49708c947863eef631efRonghua Wu    if (mLatestBufferId >= 0) {
57537b2b389139ed638831e49708c947863eef631efRonghua Wu        if (mLatestBufferUseCount == 0) {
576d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            if (mIsPersistent) {
577d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->detachBuffer(mLatestBufferId);
578d291c222357303b9611cab89d0c3b047584ef377Chong Zhang
579d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                int outSlot;
580d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->attachBuffer(&outSlot, mBufferSlot[mLatestBufferId]);
581d291c222357303b9611cab89d0c3b047584ef377Chong Zhang
582d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->releaseBuffer(outSlot, 0,
58315ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, mLatestBufferFence);
584d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            } else {
585d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->releaseBuffer(
586d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                        mLatestBufferId, mLatestBufferFrameNum,
58715ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, mLatestBufferFence);
588d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            }
58915ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            // mLatestBufferFence will be set to new fence just below
590a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
591a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
592a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
59337b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferId = item.mBuf;
59437b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferFrameNum = item.mFrameNumber;
59594ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
59694ee4b708acfa941581160b267afb79192b1d816Chong Zhang
59737b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferUseCount = dropped ? 0 : 1;
598a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred = false;
59994ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mRepeatLastFrameCount = kRepeatLastFrameCount;
60015ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar    mLatestBufferFence = item.mFence;
601a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
602a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mReflector != NULL) {
6031d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
604a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        msg->setInt32("generation", ++mRepeatLastFrameGeneration);
605a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        msg->post(mRepeatAfterUs);
606a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
607a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
608a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
609ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenstatus_t GraphicBufferSource::signalEndOfInputStream() {
610f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
611a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("signalEndOfInputStream: exec=%d avail=%zu eos=%d",
612ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden            mExecuting, mNumFramesAvailable, mEndOfStream);
613ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
614ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    if (mEndOfStream) {
615ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        ALOGE("EOS was already signaled");
616ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        return INVALID_OPERATION;
617ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    }
618f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
619f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Set the end-of-stream flag.  If no frames are pending from the
620f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // BufferQueue, and a codec buffer is available, and we're executing,
621f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // we initiate the EOS from here.  Otherwise, we'll let
622f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // codecBufferEmptied() (or omxExecuting) do it.
623f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //
624f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note: if there are no pending frames and all codec buffers are
625f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // available, we *must* submit the EOS from here or we'll just
626f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // stall since no future events are expected.
627f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream = true;
628f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
629f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting && mNumFramesAvailable == 0) {
630f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
631f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
632ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
633ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    return OK;
634f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
635f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
6368ed8ceda7cfe29e8417142ef460cd70060204459Dan Stozaint64_t GraphicBufferSource::getTimestamp(const BufferItem &item) {
63794ee4b708acfa941581160b267afb79192b1d816Chong Zhang    int64_t timeUs = item.mTimestamp / 1000;
63894ee4b708acfa941581160b267afb79192b1d816Chong Zhang
6392c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    if (mTimePerCaptureUs > 0ll) {
6402c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        // Time lapse or slow motion mode
6412c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        if (mPrevCaptureUs < 0ll) {
6422c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            // first capture
6432c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            mPrevCaptureUs = timeUs;
6442c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            mPrevFrameUs = timeUs;
6452c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        } else {
6462c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            // snap to nearest capture point
6472c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            int64_t nFrames = (timeUs + mTimePerCaptureUs / 2 - mPrevCaptureUs)
6482c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                    / mTimePerCaptureUs;
6492c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            if (nFrames <= 0) {
6502c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                // skip this frame as it's too close to previous capture
651a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
6522c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                return -1;
6532c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            }
6542c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            mPrevCaptureUs = mPrevCaptureUs + nFrames * mTimePerCaptureUs;
6552c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            mPrevFrameUs += mTimePerFrameUs * nFrames;
6562c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        }
6572c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
6582c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
659a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                static_cast<long long>(timeUs),
660a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                static_cast<long long>(mPrevCaptureUs),
661a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                static_cast<long long>(mPrevFrameUs));
6622c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
6632c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        return mPrevFrameUs;
6642c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    } else if (mMaxTimestampGapUs > 0ll) {
66594ee4b708acfa941581160b267afb79192b1d816Chong Zhang        /* Cap timestamp gap between adjacent frames to specified max
66694ee4b708acfa941581160b267afb79192b1d816Chong Zhang         *
66794ee4b708acfa941581160b267afb79192b1d816Chong Zhang         * In the scenario of cast mirroring, encoding could be suspended for
66894ee4b708acfa941581160b267afb79192b1d816Chong Zhang         * prolonged periods. Limiting the pts gap to workaround the problem
66994ee4b708acfa941581160b267afb79192b1d816Chong Zhang         * where encoder's rate control logic produces huge frames after a
67094ee4b708acfa941581160b267afb79192b1d816Chong Zhang         * long period of suspension.
67194ee4b708acfa941581160b267afb79192b1d816Chong Zhang         */
67294ee4b708acfa941581160b267afb79192b1d816Chong Zhang
67394ee4b708acfa941581160b267afb79192b1d816Chong Zhang        int64_t originalTimeUs = timeUs;
67494ee4b708acfa941581160b267afb79192b1d816Chong Zhang        if (mPrevOriginalTimeUs >= 0ll) {
67594ee4b708acfa941581160b267afb79192b1d816Chong Zhang            if (originalTimeUs < mPrevOriginalTimeUs) {
67694ee4b708acfa941581160b267afb79192b1d816Chong Zhang                // Drop the frame if it's going backward in time. Bad timestamp
67794ee4b708acfa941581160b267afb79192b1d816Chong Zhang                // could disrupt encoder's rate control completely.
678b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang                ALOGW("Dropping frame that's going backward in time");
67994ee4b708acfa941581160b267afb79192b1d816Chong Zhang                return -1;
68094ee4b708acfa941581160b267afb79192b1d816Chong Zhang            }
68194ee4b708acfa941581160b267afb79192b1d816Chong Zhang            int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
68294ee4b708acfa941581160b267afb79192b1d816Chong Zhang            timeUs = (timestampGapUs < mMaxTimestampGapUs ?
68394ee4b708acfa941581160b267afb79192b1d816Chong Zhang                    timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
68494ee4b708acfa941581160b267afb79192b1d816Chong Zhang        }
68594ee4b708acfa941581160b267afb79192b1d816Chong Zhang        mPrevOriginalTimeUs = originalTimeUs;
68694ee4b708acfa941581160b267afb79192b1d816Chong Zhang        mPrevModifiedTimeUs = timeUs;
68794ee4b708acfa941581160b267afb79192b1d816Chong Zhang        mOriginalTimeUs.add(timeUs, originalTimeUs);
688a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("IN  timestamp: %lld -> %lld",
689a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            static_cast<long long>(originalTimeUs),
690a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            static_cast<long long>(timeUs));
69194ee4b708acfa941581160b267afb79192b1d816Chong Zhang    }
69294ee4b708acfa941581160b267afb79192b1d816Chong Zhang
69394ee4b708acfa941581160b267afb79192b1d816Chong Zhang    return timeUs;
69494ee4b708acfa941581160b267afb79192b1d816Chong Zhang}
69594ee4b708acfa941581160b267afb79192b1d816Chong Zhang
69615ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnarstatus_t GraphicBufferSource::submitBuffer_l(const BufferItem &item, int cbi) {
697f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("submitBuffer_l cbi=%d", cbi);
698b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang
699b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang    int64_t timeUs = getTimestamp(item);
700b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang    if (timeUs < 0ll) {
701b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang        return UNKNOWN_ERROR;
702b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang    }
703b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang
704f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
705d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf];
706d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mBuf = item.mBuf;
707d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mFrameNumber = item.mFrameNumber;
708f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
709f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
710054219874873b41f1c815552987c10465c34ba2bLajos Molnar    sp<GraphicBuffer> buffer = codecBuffer.mGraphicBuffer;
711054219874873b41f1c815552987c10465c34ba2bLajos Molnar    status_t err = mNodeInstance->emptyGraphicBuffer(
71215ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            header, buffer, OMX_BUFFERFLAG_ENDOFFRAME, timeUs,
71315ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            item.mFence->isValid() ? item.mFence->dup() : -1);
714f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
715054219874873b41f1c815552987c10465c34ba2bLajos Molnar        ALOGW("WARNING: emptyNativeWindowBuffer failed: 0x%x", err);
716f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        codecBuffer.mGraphicBuffer = NULL;
717f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return err;
718f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
719f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
720054219874873b41f1c815552987c10465c34ba2bLajos Molnar    ALOGV("emptyNativeWindowBuffer succeeded, h=%p p=%p buf=%p bufhandle=%p",
721054219874873b41f1c815552987c10465c34ba2bLajos Molnar            header, header->pBuffer, buffer->getNativeBuffer(), buffer->handle);
722f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return OK;
723f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
724f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
725f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::submitEndOfInputStream_l() {
726f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mEndOfStream);
727f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStreamSent) {
728f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("EOS already sent");
729f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
730f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
731f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
732f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
733f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
734f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: no codec buffers available");
735f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
736f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
737f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
738f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // We reject any additional incoming graphic buffers, so there's no need
739f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as
740f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // in-use.
741f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
742f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
743f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
744054219874873b41f1c815552987c10465c34ba2bLajos Molnar    status_t err = mNodeInstance->emptyGraphicBuffer(
745054219874873b41f1c815552987c10465c34ba2bLajos Molnar            header, NULL /* buffer */, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
74615ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            0 /* timestamp */, -1 /* fenceFd */);
747f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
748f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
749f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else {
750f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d",
751f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                header, cbi);
7520c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mEndOfStreamSent = true;
753f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
754f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
755f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
756f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findAvailableCodecBuffer_l() {
757f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mCodecBuffers.size() > 0);
758f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
759f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
760f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mGraphicBuffer == NULL) {
761f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
762f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
763f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
764f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
765f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
766f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
767f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findMatchingCodecBuffer_l(
768f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        const OMX_BUFFERHEADERTYPE* header) {
769f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
770f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mHeader == header) {
771f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
772f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
773f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
774f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
775f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
776f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
777f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
77804f101c35eaa90b1f95939afac30674ec1611e6fDan Stozavoid GraphicBufferSource::onFrameAvailable(const BufferItem& /*item*/) {
779f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
780f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
781a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("onFrameAvailable exec=%d avail=%zu",
7820c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mExecuting, mNumFramesAvailable);
783f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
784e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mEndOfStream || mSuspended) {
785e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        if (mEndOfStream) {
786e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // This should only be possible if a new buffer was queued after
787e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // EOS was signaled, i.e. the app is misbehaving.
788e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
789e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGW("onFrameAvailable: EOS is set, ignoring frame");
790e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        } else {
791e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGV("onFrameAvailable: suspended, ignoring frame");
792e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
793f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
7948ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza        BufferItem item;
7955205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza        status_t err = mConsumer->acquireBuffer(&item, 0);
796f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (err == OK) {
79749270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang            // If this is the first time we're seeing this buffer, add it to our
79849270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang            // slot table.
79949270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang            if (item.mGraphicBuffer != NULL) {
8002c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mBuf);
80149270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang                mBufferSlot[item.mBuf] = item.mGraphicBuffer;
80249270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang            }
803d291c222357303b9611cab89d0c3b047584ef377Chong Zhang
804d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            if (mIsPersistent) {
805d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->detachBuffer(item.mBuf);
806d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->attachBuffer(&item.mBuf, item.mGraphicBuffer);
807d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->releaseBuffer(item.mBuf, 0,
80815ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
809d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            } else {
810d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
811d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                        EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
812d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            }
813f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
814f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
815f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
816f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
817f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable++;
818f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
819a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred = false;
820a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    ++mRepeatLastFrameGeneration;
821a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
822f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
823f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
824f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
825f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
826f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
827f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
828f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::onBuffersReleased() {
829f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock lock(mMutex);
830f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
8312475264264b51a7592c5b2e4cd6cfdaddba16644Dan Stoza    uint64_t slotMask;
8325205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza    if (mConsumer->getReleasedBuffers(&slotMask) != NO_ERROR) {
833f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("onBuffersReleased: unable to get released buffer set");
8342475264264b51a7592c5b2e4cd6cfdaddba16644Dan Stoza        slotMask = 0xffffffffffffffffULL;
835f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
836f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
8372475264264b51a7592c5b2e4cd6cfdaddba16644Dan Stoza    ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
838f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
839f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
840f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if ((slotMask & 0x01) != 0) {
841f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mBufferSlot[i] = NULL;
842f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
843f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        slotMask >>= 1;
844f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
845f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
846f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
8478dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hall// BufferQueue::ConsumerListener callback
8488dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hallvoid GraphicBufferSource::onSidebandStreamChanged() {
8498dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hall    ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
8508dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hall}
8518dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hall
852a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huberstatus_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(
853a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        int64_t repeatAfterUs) {
854a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    Mutex::Autolock autoLock(mMutex);
855a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
856a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mExecuting || repeatAfterUs <= 0ll) {
857a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return INVALID_OPERATION;
858a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
859a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
860a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatAfterUs = repeatAfterUs;
861a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
862a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    return OK;
863a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
864a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
86594ee4b708acfa941581160b267afb79192b1d816Chong Zhangstatus_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) {
86694ee4b708acfa941581160b267afb79192b1d816Chong Zhang    Mutex::Autolock autoLock(mMutex);
86794ee4b708acfa941581160b267afb79192b1d816Chong Zhang
86894ee4b708acfa941581160b267afb79192b1d816Chong Zhang    if (mExecuting || maxGapUs <= 0ll) {
86994ee4b708acfa941581160b267afb79192b1d816Chong Zhang        return INVALID_OPERATION;
87094ee4b708acfa941581160b267afb79192b1d816Chong Zhang    }
87194ee4b708acfa941581160b267afb79192b1d816Chong Zhang
87294ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mMaxTimestampGapUs = maxGapUs;
87394ee4b708acfa941581160b267afb79192b1d816Chong Zhang
87494ee4b708acfa941581160b267afb79192b1d816Chong Zhang    return OK;
87594ee4b708acfa941581160b267afb79192b1d816Chong Zhang}
87672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
87737b2b389139ed638831e49708c947863eef631efRonghua Wustatus_t GraphicBufferSource::setMaxFps(float maxFps) {
87837b2b389139ed638831e49708c947863eef631efRonghua Wu    Mutex::Autolock autoLock(mMutex);
87937b2b389139ed638831e49708c947863eef631efRonghua Wu
88037b2b389139ed638831e49708c947863eef631efRonghua Wu    if (mExecuting) {
88137b2b389139ed638831e49708c947863eef631efRonghua Wu        return INVALID_OPERATION;
88237b2b389139ed638831e49708c947863eef631efRonghua Wu    }
88337b2b389139ed638831e49708c947863eef631efRonghua Wu
88437b2b389139ed638831e49708c947863eef631efRonghua Wu    mFrameDropper = new FrameDropper();
88537b2b389139ed638831e49708c947863eef631efRonghua Wu    status_t err = mFrameDropper->setMaxFrameRate(maxFps);
88637b2b389139ed638831e49708c947863eef631efRonghua Wu    if (err != OK) {
88737b2b389139ed638831e49708c947863eef631efRonghua Wu        mFrameDropper.clear();
88837b2b389139ed638831e49708c947863eef631efRonghua Wu        return err;
88937b2b389139ed638831e49708c947863eef631efRonghua Wu    }
89037b2b389139ed638831e49708c947863eef631efRonghua Wu
89137b2b389139ed638831e49708c947863eef631efRonghua Wu    return OK;
89237b2b389139ed638831e49708c947863eef631efRonghua Wu}
89337b2b389139ed638831e49708c947863eef631efRonghua Wu
89472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid GraphicBufferSource::setSkipFramesBeforeUs(int64_t skipFramesBeforeUs) {
89572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Mutex::Autolock autoLock(mMutex);
89672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
89772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSkipFramesBeforeNs =
89872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll;
89972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
90072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9012c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhangstatus_t GraphicBufferSource::setTimeLapseUs(int64_t* data) {
9022c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    Mutex::Autolock autoLock(mMutex);
9032c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
9042c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    if (mExecuting || data[0] <= 0ll || data[1] <= 0ll) {
9052c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        return INVALID_OPERATION;
9062c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    }
9072c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
9082c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mTimePerFrameUs = data[0];
9092c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mTimePerCaptureUs = data[1];
9102c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
9112c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    return OK;
9122c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang}
9132c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
914a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Hubervoid GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
915a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    switch (msg->what()) {
916a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        case kWhatRepeatLastFrame:
917a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        {
918a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            Mutex::Autolock autoLock(mMutex);
919a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
920a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            int32_t generation;
921a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            CHECK(msg->findInt32("generation", &generation));
922a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
923a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (generation != mRepeatLastFrameGeneration) {
924a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                // stale
925a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                break;
926a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
927a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
928a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (!mExecuting || mNumFramesAvailable > 0) {
929a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                break;
930a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
931a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
93237b2b389139ed638831e49708c947863eef631efRonghua Wu            bool success = repeatLatestBuffer_l();
933a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
934a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (success) {
93537b2b389139ed638831e49708c947863eef631efRonghua Wu                ALOGV("repeatLatestBuffer_l SUCCESS");
936a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            } else {
93737b2b389139ed638831e49708c947863eef631efRonghua Wu                ALOGV("repeatLatestBuffer_l FAILURE");
938a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                mRepeatBufferDeferred = true;
939a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
940a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            break;
941a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
942a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
943a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        default:
944a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            TRESPASS();
945a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
946a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
947a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
948f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}  // namespace android
949