GraphicBufferSource.cpp revision 264bac95912efe121d6a60026612617f04f42966
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
41ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong ZhangGraphicBufferSource::PersistentProxyListener::PersistentProxyListener(
42ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        const wp<IGraphicBufferConsumer> &consumer,
43ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        const wp<ConsumerListener>& consumerListener) :
44ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    mConsumerListener(consumerListener),
45ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    mConsumer(consumer) {}
46ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang
47ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong ZhangGraphicBufferSource::PersistentProxyListener::~PersistentProxyListener() {}
48ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang
49ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhangvoid GraphicBufferSource::PersistentProxyListener::onFrameAvailable(
50ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        const BufferItem& item) {
51ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    sp<ConsumerListener> listener(mConsumerListener.promote());
52ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    if (listener != NULL) {
53ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        listener->onFrameAvailable(item);
54ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    } else {
55ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        sp<IGraphicBufferConsumer> consumer(mConsumer.promote());
56ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        if (consumer == NULL) {
57ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang            return;
58ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        }
59ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        BufferItem bi;
60ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        status_t err = consumer->acquireBuffer(&bi, 0);
61ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        if (err != OK) {
62ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang            ALOGE("PersistentProxyListener: acquireBuffer failed (%d)", err);
63ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang            return;
64ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        }
65ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang
66ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        err = consumer->detachBuffer(bi.mBuf);
67ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        if (err != OK) {
68ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang            ALOGE("PersistentProxyListener: detachBuffer failed (%d)", err);
69ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang            return;
70ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        }
71ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang
72ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        err = consumer->attachBuffer(&bi.mBuf, bi.mGraphicBuffer);
73ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        if (err != OK) {
74ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang            ALOGE("PersistentProxyListener: attachBuffer failed (%d)", err);
75ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang            return;
76ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        }
77ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang
78ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        err = consumer->releaseBuffer(bi.mBuf, 0,
79ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, bi.mFence);
80ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        if (err != OK) {
81ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang            ALOGE("PersistentProxyListener: releaseBuffer failed (%d)", err);
82ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        }
83ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    }
84ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang}
85ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang
86ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhangvoid GraphicBufferSource::PersistentProxyListener::onFrameReplaced(
87ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        const BufferItem& item) {
88ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    sp<ConsumerListener> listener(mConsumerListener.promote());
89ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    if (listener != NULL) {
90ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        listener->onFrameReplaced(item);
91ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    }
92ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang}
93ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang
94ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhangvoid GraphicBufferSource::PersistentProxyListener::onBuffersReleased() {
95ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    sp<ConsumerListener> listener(mConsumerListener.promote());
96ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    if (listener != NULL) {
97ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        listener->onBuffersReleased();
98ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    }
99ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang}
100ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang
101ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhangvoid GraphicBufferSource::PersistentProxyListener::onSidebandStreamChanged() {
102ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    sp<ConsumerListener> listener(mConsumerListener.promote());
103ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    if (listener != NULL) {
104ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        listener->onSidebandStreamChanged();
105ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    }
106ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang}
107f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
108d291c222357303b9611cab89d0c3b047584ef377Chong ZhangGraphicBufferSource::GraphicBufferSource(
109d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        OMXNodeInstance* nodeInstance,
110d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        uint32_t bufferWidth,
111d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        uint32_t bufferHeight,
112d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        uint32_t bufferCount,
113d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        const sp<IGraphicBufferConsumer> &consumer) :
114f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mInitCheck(UNKNOWN_ERROR),
115f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNodeInstance(nodeInstance),
116f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting(false),
117e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended(false),
118d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    mIsPersistent(false),
119d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    mConsumer(consumer),
120f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable(0),
1219700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    mNumBufferAcquired(0),
122f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream(false),
123a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mEndOfStreamSent(false),
12494ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mMaxTimestampGapUs(-1ll),
12594ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mPrevOriginalTimeUs(-1ll),
12694ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mPrevModifiedTimeUs(-1ll),
12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSkipFramesBeforeNs(-1ll),
12884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    mRepeatAfterUs(-1ll),
129a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatLastFrameGeneration(0),
13094ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mRepeatLastFrameTimestamp(-1ll),
13137b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferId(-1),
13237b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferFrameNum(0),
13337b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferUseCount(0),
13415ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar    mLatestBufferFence(Fence::NO_FENCE),
1352c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mRepeatBufferDeferred(false),
1362c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mTimePerCaptureUs(-1ll),
1372c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mTimePerFrameUs(-1ll),
1382c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mPrevCaptureUs(-1ll),
139054219874873b41f1c815552987c10465c34ba2bLajos Molnar    mPrevFrameUs(-1ll) {
140f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
1410c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    ALOGV("GraphicBufferSource w=%u h=%u c=%u",
1420c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            bufferWidth, bufferHeight, bufferCount);
143f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
144f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (bufferWidth == 0 || bufferHeight == 0) {
1450c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
146f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        mInitCheck = BAD_VALUE;
147f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
148f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
149f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
150d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    if (mConsumer == NULL) {
151d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        String8 name("GraphicBufferSource");
1520c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
153d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
154d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        mConsumer->setConsumerName(name);
155d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
156d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
157d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        if (mInitCheck != NO_ERROR) {
158d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
159d291c222357303b9611cab89d0c3b047584ef377Chong Zhang                    bufferCount, mInitCheck);
160d291c222357303b9611cab89d0c3b047584ef377Chong Zhang            return;
161d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        }
162d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    } else {
163d291c222357303b9611cab89d0c3b047584ef377Chong Zhang        mIsPersistent = true;
1640c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
165d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
166f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
167f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // reference once the ctor ends, as that would cause the refcount of 'this'
168f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
169f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that's what we create.
170910813bd66eaf0f6a72769c9b3fa9830dd100a19Mathias Agopian    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
171ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    sp<IConsumerListener> proxy;
172ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    if (!mIsPersistent) {
173ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        proxy = new BufferQueue::ProxyConsumerListener(listener);
174ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    } else {
175ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang        proxy = new PersistentProxyListener(mConsumer, listener);
176ffd8cbb288f096b53df0392bf40d99b89e34bea7Chong Zhang    }
177f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
1785205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza    mInitCheck = mConsumer->consumerConnect(proxy, false);
1790c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (mInitCheck != NO_ERROR) {
180f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("Error connecting to BufferQueue: %s (%d)",
1810c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                strerror(-mInitCheck), mInitCheck);
182f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
183f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
184f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
1850c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    CHECK(mInitCheck == NO_ERROR);
186f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
187f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
188f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenGraphicBufferSource::~GraphicBufferSource() {
1899700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    if (mLatestBufferId >= 0) {
1909700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang        releaseBuffer(
1919700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang                mLatestBufferId, mLatestBufferFrameNum,
1929700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang                mBufferSlot[mLatestBufferId], mLatestBufferFence);
1939700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    }
1949700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    if (mNumBufferAcquired != 0) {
1959700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang        ALOGW("potential buffer leak (acquired %d)", mNumBufferAcquired);
1969700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    }
197d291c222357303b9611cab89d0c3b047584ef377Chong Zhang    if (mConsumer != NULL && !mIsPersistent) {
1985205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza        status_t err = mConsumer->consumerDisconnect();
1990c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        if (err != NO_ERROR) {
2000c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            ALOGW("consumerDisconnect failed: %d", err);
2010c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        }
202f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
203f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
204f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
205f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::omxExecuting() {
206f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
207a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("--> executing; avail=%zu, codec vec size=%zd",
208f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mCodecBuffers.size());
209f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(!mExecuting);
210f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = true;
211f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
212f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Start by loading up as many buffers as possible.  We want to do this,
213f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // rather than just submit the first buffer, to avoid a degenerate case:
214f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // if all BQ buffers arrive before we start executing, and we only submit
215f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // one here, the other BQ buffers will just sit until we get notified
216f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that the codec buffer has been released.  We'd then acquire and
217f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // submit a single additional buffer, repeatedly, never using more than
218f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // one codec buffer simultaneously.  (We could instead try to submit
219f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // all BQ buffers whenever any codec buffer is freed, but if we get the
220f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // initial conditions right that will never be useful.)
2210c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    while (mNumFramesAvailable) {
2220c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        if (!fillCodecBuffer_l()) {
2230c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            ALOGV("stop load with frames available (codecAvail=%d)",
2240c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                    isCodecBufferAvailable_l());
2250c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            break;
2260c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        }
227f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
228f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
229a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("done loading initial frames, avail=%zu", mNumFramesAvailable);
230f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
231f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If EOS has already been signaled, and there are no more frames to
232f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // submit, try to send EOS now as well.
233f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStream && mNumFramesAvailable == 0) {
234f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
235f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
236a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
237a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mRepeatAfterUs > 0ll && mLooper == NULL) {
238a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mReflector = new AHandlerReflector<GraphicBufferSource>(this);
239a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
240a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper = new ALooper;
241a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->registerHandler(mReflector);
242a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->start();
243a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
24437b2b389139ed638831e49708c947863eef631efRonghua Wu        if (mLatestBufferId >= 0) {
245a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            sp<AMessage> msg =
2461d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                new AMessage(kWhatRepeatLastFrame, mReflector);
247a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
248a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            msg->setInt32("generation", ++mRepeatLastFrameGeneration);
249a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            msg->post(mRepeatAfterUs);
250a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
251a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
252f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
253f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
254ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Hubervoid GraphicBufferSource::omxIdle() {
255ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    ALOGV("omxIdle");
256ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
257ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    Mutex::Autolock autoLock(mMutex);
258ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
259ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    if (mExecuting) {
260ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber        // We are only interested in the transition from executing->idle,
261ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber        // not loaded->idle.
262892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber        mExecuting = false;
263ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber    }
264ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber}
265ad3b7e8d40bf1c97347f1538d30bba78ca371f67Andreas Huber
266ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenvoid GraphicBufferSource::omxLoaded(){
267f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
268ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    if (!mExecuting) {
269ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        // This can happen if something failed very early.
270ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden        ALOGW("Dropped back down to Loaded without Executing");
271ba812e3b3ca0a0c9459fe29bbc211c9a73313b8bAndy McFadden    }
272f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
273a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mLooper != NULL) {
274a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->unregisterHandler(mReflector->id());
275a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mReflector.clear();
276a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
277a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper->stop();
278a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mLooper.clear();
279a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
280a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
281a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d",
282f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
283f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
284f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Codec is no longer executing.  Discard all codec-related state.
285f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.clear();
286f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
287f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //       are null; complain if not
288f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
289f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mExecuting = false;
290f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
291f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
292f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) {
293f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
294f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
295f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
296f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen -- buffers can only be allocated when
297f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // transitioning from "loaded" to "idle".
298f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("addCodecBuffer: buffer added while executing");
299f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
300f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
301f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
302db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn    ALOGV("addCodecBuffer h=%p size=%" PRIu32 " p=%p",
303f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->pBuffer);
304f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer codecBuffer;
305f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mHeader = header;
306f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mCodecBuffers.add(codecBuffer);
307f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
308f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
30915ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnarvoid GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header, int fenceFd) {
310f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
311892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber    if (!mExecuting) {
312892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber        return;
313892e1b9ab055075ba9036fb7dd6404e9e0f2677aAndreas Huber    }
314f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
315f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findMatchingCodecBuffer_l(header);
316f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
317f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // This should never happen.
318f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header);
31915ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        if (fenceFd >= 0) {
32015ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            ::close(fenceFd);
32115ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        }
322f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
323f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
324f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
325db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn    ALOGV("codecBufferEmptied h=%p size=%" PRIu32 " filled=%" PRIu32 " p=%p",
326f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header, header->nAllocLen, header->nFilledLen,
327f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            header->pBuffer);
328f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
329f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
330f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // header->nFilledLen may not be the original value, so we can't compare
331f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // that to zero to see of this was the EOS buffer.  Instead we just
332f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // see if the GraphicBuffer reference was null, which should only ever
333f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // happen for EOS.
334f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (codecBuffer.mGraphicBuffer == NULL) {
3355572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden        if (!(mEndOfStream && mEndOfStreamSent)) {
3365572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            // This can happen when broken code sends us the same buffer
3375572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            // twice in a row.
3385572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden            ALOGE("ERROR: codecBufferEmptied on non-EOS null buffer "
3395572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden                    "(buffer emptied twice?)");
3405572b3afe3e63110ef9e6d228112ca7cbfac866bAndy McFadden        }
341f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No GraphicBuffer to deal with, no additional input or output is
342f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // expected, so just return.
34315ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        if (fenceFd >= 0) {
34415ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            ::close(fenceFd);
34515ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        }
346f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
347f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
348f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
349054219874873b41f1c815552987c10465c34ba2bLajos Molnar    if (EXTRA_CHECK && header->nAllocLen >= sizeof(MetadataBufferType)) {
350f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Pull the graphic buffer handle back out of the buffer, and confirm
351f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // that it matches expectations.
352f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        OMX_U8* data = header->pBuffer;
353512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar        MetadataBufferType type = *(MetadataBufferType *)data;
354054219874873b41f1c815552987c10465c34ba2bLajos Molnar        if (type == kMetadataBufferTypeGrallocSource
355054219874873b41f1c815552987c10465c34ba2bLajos Molnar                && header->nAllocLen >= sizeof(VideoGrallocMetadata)) {
356054219874873b41f1c815552987c10465c34ba2bLajos Molnar            VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)data;
3579847fcefb183e1cb09eb48e17a09577392b0e8f4Lajos Molnar            if (grallocMeta.pHandle != codecBuffer.mGraphicBuffer->handle) {
358512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                // should never happen
359512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
3609847fcefb183e1cb09eb48e17a09577392b0e8f4Lajos Molnar                        grallocMeta.pHandle, codecBuffer.mGraphicBuffer->handle);
361512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                CHECK(!"codecBufferEmptied: mismatched buffer");
362512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar            }
363054219874873b41f1c815552987c10465c34ba2bLajos Molnar        } else if (type == kMetadataBufferTypeANWBuffer
364054219874873b41f1c815552987c10465c34ba2bLajos Molnar                && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
365054219874873b41f1c815552987c10465c34ba2bLajos Molnar            VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)data;
366054219874873b41f1c815552987c10465c34ba2bLajos Molnar            if (nativeMeta.pBuffer != codecBuffer.mGraphicBuffer->getNativeBuffer()) {
367512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                // should never happen
368512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                ALOGE("codecBufferEmptied: buffer is %p, expected %p",
369054219874873b41f1c815552987c10465c34ba2bLajos Molnar                        nativeMeta.pBuffer, codecBuffer.mGraphicBuffer->getNativeBuffer());
370512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar                CHECK(!"codecBufferEmptied: mismatched buffer");
371512e979284de984427e5b2f73b9054ae1b5e2b0aLajos Molnar            }
372f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
373f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
374f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
375f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Find matching entry in our cached copy of the BufferQueue slots.
376f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // If we find a match, release that slot.  If we don't, the BufferQueue
377f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // has dropped that GraphicBuffer, and there's nothing for us to release.
378d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    int id = codecBuffer.mBuf;
37915ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar    sp<Fence> fence = new Fence(fenceFd);
380d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    if (mBufferSlot[id] != NULL &&
381d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
382d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar        ALOGV("cbi %d matches bq slot %d, handle=%p",
383d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar                cbi, id, mBufferSlot[id]->handle);
384d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar
38537b2b389139ed638831e49708c947863eef631efRonghua Wu        if (id == mLatestBufferId) {
38637b2b389139ed638831e49708c947863eef631efRonghua Wu            CHECK_GT(mLatestBufferUseCount--, 0);
387a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
3889700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang            releaseBuffer(id, codecBuffer.mFrameNumber, mBufferSlot[id], fence);
389a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
390d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    } else {
391f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
392f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                cbi);
39315ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        // we will not reuse codec buffer, so there is no need to wait for fence
394f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
395f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
396f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Mark the codec buffer as available by clearing the GraphicBuffer ref.
397f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    codecBuffer.mGraphicBuffer = NULL;
398f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
399f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mNumFramesAvailable) {
400f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // Fill this codec buffer.
4010c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        CHECK(!mEndOfStreamSent);
402a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("buffer freed, %zu frames avail (eos=%d)",
4030c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden                mNumFramesAvailable, mEndOfStream);
404f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
405f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else if (mEndOfStream) {
406f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No frames available, but EOS is pending, so use this buffer to
407f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // send that.
408f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("buffer freed, EOS pending");
409f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
410a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    } else if (mRepeatBufferDeferred) {
41137b2b389139ed638831e49708c947863eef631efRonghua Wu        bool success = repeatLatestBuffer_l();
412a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        if (success) {
41337b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("deferred repeatLatestBuffer_l SUCCESS");
414a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
41537b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("deferred repeatLatestBuffer_l FAILURE");
416a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
417a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        mRepeatBufferDeferred = false;
418f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
419a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
420f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return;
421f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
422f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
42394ee4b708acfa941581160b267afb79192b1d816Chong Zhangvoid GraphicBufferSource::codecBufferFilled(OMX_BUFFERHEADERTYPE* header) {
42494ee4b708acfa941581160b267afb79192b1d816Chong Zhang    Mutex::Autolock autoLock(mMutex);
42594ee4b708acfa941581160b267afb79192b1d816Chong Zhang
42694ee4b708acfa941581160b267afb79192b1d816Chong Zhang    if (mMaxTimestampGapUs > 0ll
42794ee4b708acfa941581160b267afb79192b1d816Chong Zhang            && !(header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
42894ee4b708acfa941581160b267afb79192b1d816Chong Zhang        ssize_t index = mOriginalTimeUs.indexOfKey(header->nTimeStamp);
42994ee4b708acfa941581160b267afb79192b1d816Chong Zhang        if (index >= 0) {
43094ee4b708acfa941581160b267afb79192b1d816Chong Zhang            ALOGV("OUT timestamp: %lld -> %lld",
431a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                    static_cast<long long>(header->nTimeStamp),
432a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                    static_cast<long long>(mOriginalTimeUs[index]));
43394ee4b708acfa941581160b267afb79192b1d816Chong Zhang            header->nTimeStamp = mOriginalTimeUs[index];
43494ee4b708acfa941581160b267afb79192b1d816Chong Zhang            mOriginalTimeUs.removeItemsAt(index);
43594ee4b708acfa941581160b267afb79192b1d816Chong Zhang        } else {
43694ee4b708acfa941581160b267afb79192b1d816Chong Zhang            // giving up the effort as encoder doesn't appear to preserve pts
43794ee4b708acfa941581160b267afb79192b1d816Chong Zhang            ALOGW("giving up limiting timestamp gap (pts = %lld)",
43894ee4b708acfa941581160b267afb79192b1d816Chong Zhang                    header->nTimeStamp);
43994ee4b708acfa941581160b267afb79192b1d816Chong Zhang            mMaxTimestampGapUs = -1ll;
44094ee4b708acfa941581160b267afb79192b1d816Chong Zhang        }
44194ee4b708acfa941581160b267afb79192b1d816Chong Zhang        if (mOriginalTimeUs.size() > BufferQueue::NUM_BUFFER_SLOTS) {
44294ee4b708acfa941581160b267afb79192b1d816Chong Zhang            // something terribly wrong must have happened, giving up...
443a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            ALOGE("mOriginalTimeUs has too many entries (%zu)",
44494ee4b708acfa941581160b267afb79192b1d816Chong Zhang                    mOriginalTimeUs.size());
44594ee4b708acfa941581160b267afb79192b1d816Chong Zhang            mMaxTimestampGapUs = -1ll;
44694ee4b708acfa941581160b267afb79192b1d816Chong Zhang        }
44794ee4b708acfa941581160b267afb79192b1d816Chong Zhang    }
44894ee4b708acfa941581160b267afb79192b1d816Chong Zhang}
44994ee4b708acfa941581160b267afb79192b1d816Chong Zhang
450e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Hubervoid GraphicBufferSource::suspend(bool suspend) {
451e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    Mutex::Autolock autoLock(mMutex);
452e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
453e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (suspend) {
454e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        mSuspended = true;
455e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
456e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        while (mNumFramesAvailable > 0) {
4578ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza            BufferItem item;
4585205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza            status_t err = mConsumer->acquireBuffer(&item, 0);
459e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
460e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
461e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                // shouldn't happen.
462e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: frame was not available");
463e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
464e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            } else if (err != OK) {
465e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                ALOGW("suspend: acquireBuffer returned err=%d", err);
466e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber                break;
467e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            }
468e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
4699700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang            ++mNumBufferAcquired;
470e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            --mNumFramesAvailable;
471e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
4729700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang            releaseBuffer(item.mBuf, item.mFrameNumber,
4739700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang                    item.mGraphicBuffer, item.mFence);
474e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
475e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return;
476e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
477e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
478e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    mSuspended = false;
479a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
480a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
48137b2b389139ed638831e49708c947863eef631efRonghua Wu        if (repeatLatestBuffer_l()) {
48237b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
483a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
484a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            mRepeatBufferDeferred = false;
485a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        } else {
48637b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
487a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
488a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
489e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber}
490e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
4910c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFaddenbool GraphicBufferSource::fillCodecBuffer_l() {
492f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mExecuting && mNumFramesAvailable > 0);
4930c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
494e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mSuspended) {
495e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        return false;
496e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    }
497e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
498f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
499f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
500f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        // No buffers available, bail.
501a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("fillCodecBuffer_l: no codec buffers, avail now %zu",
502f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                mNumFramesAvailable);
5030c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
5040c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
505f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
506a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
5070c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mNumFramesAvailable);
5088ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza    BufferItem item;
5095205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza    status_t err = mConsumer->acquireBuffer(&item, 0);
5100c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
5110c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // shouldn't happen
5120c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: frame was not available");
5130c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
5140c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else if (err != OK) {
5150c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        // now what? fake end-of-stream?
5160c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
5170c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        return false;
5180c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
519f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
5209700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    mNumBufferAcquired++;
5210c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    mNumFramesAvailable--;
522f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
5230c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // If this is the first time we're seeing this buffer, add it to our
5240c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    // slot table.
5250c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (item.mGraphicBuffer != NULL) {
5260c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf);
5270c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mBufferSlot[item.mBuf] = item.mGraphicBuffer;
5280c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    }
5290c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden
53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    err = UNKNOWN_ERROR;
53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    // only submit sample if start time is unspecified, or sample
53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    // is queued after the specified start time
53437b2b389139ed638831e49708c947863eef631efRonghua Wu    bool dropped = false;
53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) {
53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if start time is set, offset time stamp by start time
53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mSkipFramesBeforeNs > 0) {
53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            item.mTimestamp -= mSkipFramesBeforeNs;
53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
54037b2b389139ed638831e49708c947863eef631efRonghua Wu
54137b2b389139ed638831e49708c947863eef631efRonghua Wu        int64_t timeUs = item.mTimestamp / 1000;
54237b2b389139ed638831e49708c947863eef631efRonghua Wu        if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) {
54337b2b389139ed638831e49708c947863eef631efRonghua Wu            ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs));
54437b2b389139ed638831e49708c947863eef631efRonghua Wu            // set err to OK so that the skipped frame can still be saved as the lastest frame
54537b2b389139ed638831e49708c947863eef631efRonghua Wu            err = OK;
54637b2b389139ed638831e49708c947863eef631efRonghua Wu            dropped = true;
54737b2b389139ed638831e49708c947863eef631efRonghua Wu        } else {
54837b2b389139ed638831e49708c947863eef631efRonghua Wu            err = submitBuffer_l(item, cbi);
54937b2b389139ed638831e49708c947863eef631efRonghua Wu        }
55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5520c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    if (err != OK) {
5530c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf);
5549700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang        releaseBuffer(item.mBuf, item.mFrameNumber, item.mGraphicBuffer, item.mFence);
5550c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    } else {
5560c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi);
55737b2b389139ed638831e49708c947863eef631efRonghua Wu        setLatestBuffer_l(item, dropped);
558a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
559a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
560a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    return true;
561a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
562a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
56337b2b389139ed638831e49708c947863eef631efRonghua Wubool GraphicBufferSource::repeatLatestBuffer_l() {
564a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    CHECK(mExecuting && mNumFramesAvailable == 0);
565a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
56637b2b389139ed638831e49708c947863eef631efRonghua Wu    if (mLatestBufferId < 0 || mSuspended) {
567a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
568a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
56937b2b389139ed638831e49708c947863eef631efRonghua Wu    if (mBufferSlot[mLatestBufferId] == NULL) {
570bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // This can happen if the remote side disconnects, causing
571bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // onBuffersReleased() to NULL out our copy of the slots.  The
572bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // buffer is gone, so we have nothing to show.
573bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        //
574bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        // To be on the safe side we try to release the buffer.
57537b2b389139ed638831e49708c947863eef631efRonghua Wu        ALOGD("repeatLatestBuffer_l: slot was NULL");
5765205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza        mConsumer->releaseBuffer(
57737b2b389139ed638831e49708c947863eef631efRonghua Wu                mLatestBufferId,
57837b2b389139ed638831e49708c947863eef631efRonghua Wu                mLatestBufferFrameNum,
579bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                EGL_NO_DISPLAY,
580bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden                EGL_NO_SYNC_KHR,
58115ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar                mLatestBufferFence);
58237b2b389139ed638831e49708c947863eef631efRonghua Wu        mLatestBufferId = -1;
58337b2b389139ed638831e49708c947863eef631efRonghua Wu        mLatestBufferFrameNum = 0;
58415ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar        mLatestBufferFence = Fence::NO_FENCE;
585bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden        return false;
586bdfd4885aa4d7b3f3f591118927a3f4aec593096Andy McFadden    }
587a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
588a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    int cbi = findAvailableCodecBuffer_l();
589a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (cbi < 0) {
590a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        // No buffers available, bail.
59137b2b389139ed638831e49708c947863eef631efRonghua Wu        ALOGV("repeatLatestBuffer_l: no codec buffers.");
592a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
593a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
594a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
5958ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza    BufferItem item;
59637b2b389139ed638831e49708c947863eef631efRonghua Wu    item.mBuf = mLatestBufferId;
59737b2b389139ed638831e49708c947863eef631efRonghua Wu    item.mFrameNumber = mLatestBufferFrameNum;
59894ee4b708acfa941581160b267afb79192b1d816Chong Zhang    item.mTimestamp = mRepeatLastFrameTimestamp;
59915ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar    item.mFence = mLatestBufferFence;
600a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
601a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    status_t err = submitBuffer_l(item, cbi);
602a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
603a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (err != OK) {
604a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return false;
605f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
606f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
60737b2b389139ed638831e49708c947863eef631efRonghua Wu    ++mLatestBufferUseCount;
608a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
60994ee4b708acfa941581160b267afb79192b1d816Chong Zhang    /* repeat last frame up to kRepeatLastFrameCount times.
61094ee4b708acfa941581160b267afb79192b1d816Chong Zhang     * in case of static scene, a single repeat might not get rid of encoder
61194ee4b708acfa941581160b267afb79192b1d816Chong Zhang     * ghosting completely, refresh a couple more times to get better quality
61294ee4b708acfa941581160b267afb79192b1d816Chong Zhang     */
61394ee4b708acfa941581160b267afb79192b1d816Chong Zhang    if (--mRepeatLastFrameCount > 0) {
61494ee4b708acfa941581160b267afb79192b1d816Chong Zhang        mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
61594ee4b708acfa941581160b267afb79192b1d816Chong Zhang
61694ee4b708acfa941581160b267afb79192b1d816Chong Zhang        if (mReflector != NULL) {
6171d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
61894ee4b708acfa941581160b267afb79192b1d816Chong Zhang            msg->setInt32("generation", ++mRepeatLastFrameGeneration);
61994ee4b708acfa941581160b267afb79192b1d816Chong Zhang            msg->post(mRepeatAfterUs);
62094ee4b708acfa941581160b267afb79192b1d816Chong Zhang        }
62194ee4b708acfa941581160b267afb79192b1d816Chong Zhang    }
62294ee4b708acfa941581160b267afb79192b1d816Chong Zhang
6230c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden    return true;
624f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
625f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
62637b2b389139ed638831e49708c947863eef631efRonghua Wuvoid GraphicBufferSource::setLatestBuffer_l(
6278ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza        const BufferItem &item, bool dropped) {
62837b2b389139ed638831e49708c947863eef631efRonghua Wu    ALOGV("setLatestBuffer_l");
629a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
63037b2b389139ed638831e49708c947863eef631efRonghua Wu    if (mLatestBufferId >= 0) {
63137b2b389139ed638831e49708c947863eef631efRonghua Wu        if (mLatestBufferUseCount == 0) {
6329700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang            releaseBuffer(mLatestBufferId, mLatestBufferFrameNum,
6339700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang                    mBufferSlot[mLatestBufferId], mLatestBufferFence);
63415ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            // mLatestBufferFence will be set to new fence just below
635a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
636a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
637a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
63837b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferId = item.mBuf;
63937b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferFrameNum = item.mFrameNumber;
64094ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
64194ee4b708acfa941581160b267afb79192b1d816Chong Zhang
64237b2b389139ed638831e49708c947863eef631efRonghua Wu    mLatestBufferUseCount = dropped ? 0 : 1;
643a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred = false;
64494ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mRepeatLastFrameCount = kRepeatLastFrameCount;
64515ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar    mLatestBufferFence = item.mFence;
646a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
647a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mReflector != NULL) {
6481d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
649a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        msg->setInt32("generation", ++mRepeatLastFrameGeneration);
650a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        msg->post(mRepeatAfterUs);
651a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
652a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
653a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
654ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFaddenstatus_t GraphicBufferSource::signalEndOfInputStream() {
655f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
656a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("signalEndOfInputStream: exec=%d avail=%zu eos=%d",
657ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden            mExecuting, mNumFramesAvailable, mEndOfStream);
658ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
659ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    if (mEndOfStream) {
660ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        ALOGE("EOS was already signaled");
661ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden        return INVALID_OPERATION;
662ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    }
663f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
664f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Set the end-of-stream flag.  If no frames are pending from the
665f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // BufferQueue, and a codec buffer is available, and we're executing,
666f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // we initiate the EOS from here.  Otherwise, we'll let
667f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // codecBufferEmptied() (or omxExecuting) do it.
668f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    //
669f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // Note: if there are no pending frames and all codec buffers are
670f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // available, we *must* submit the EOS from here or we'll just
671f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // stall since no future events are expected.
672f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mEndOfStream = true;
673f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
674f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting && mNumFramesAvailable == 0) {
675f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        submitEndOfInputStream_l();
676f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
677ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden
678ba6218eae3dbcf3f962b3561b26374a214dbf5e2Andy McFadden    return OK;
679f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
680f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
6818ed8ceda7cfe29e8417142ef460cd70060204459Dan Stozaint64_t GraphicBufferSource::getTimestamp(const BufferItem &item) {
68294ee4b708acfa941581160b267afb79192b1d816Chong Zhang    int64_t timeUs = item.mTimestamp / 1000;
68394ee4b708acfa941581160b267afb79192b1d816Chong Zhang
6842c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    if (mTimePerCaptureUs > 0ll) {
6852c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        // Time lapse or slow motion mode
6862c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        if (mPrevCaptureUs < 0ll) {
6872c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            // first capture
6882c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            mPrevCaptureUs = timeUs;
6892c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            mPrevFrameUs = timeUs;
6902c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        } else {
6912c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            // snap to nearest capture point
6922c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            int64_t nFrames = (timeUs + mTimePerCaptureUs / 2 - mPrevCaptureUs)
6932c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                    / mTimePerCaptureUs;
6942c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            if (nFrames <= 0) {
6952c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                // skip this frame as it's too close to previous capture
696a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
6972c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                return -1;
6982c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            }
6992c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            mPrevCaptureUs = mPrevCaptureUs + nFrames * mTimePerCaptureUs;
7002c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang            mPrevFrameUs += mTimePerFrameUs * nFrames;
7012c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        }
7022c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
7032c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
704a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                static_cast<long long>(timeUs),
705a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                static_cast<long long>(mPrevCaptureUs),
706a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                static_cast<long long>(mPrevFrameUs));
7072c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
7082c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        return mPrevFrameUs;
7092c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    } else if (mMaxTimestampGapUs > 0ll) {
71094ee4b708acfa941581160b267afb79192b1d816Chong Zhang        /* Cap timestamp gap between adjacent frames to specified max
71194ee4b708acfa941581160b267afb79192b1d816Chong Zhang         *
71294ee4b708acfa941581160b267afb79192b1d816Chong Zhang         * In the scenario of cast mirroring, encoding could be suspended for
71394ee4b708acfa941581160b267afb79192b1d816Chong Zhang         * prolonged periods. Limiting the pts gap to workaround the problem
71494ee4b708acfa941581160b267afb79192b1d816Chong Zhang         * where encoder's rate control logic produces huge frames after a
71594ee4b708acfa941581160b267afb79192b1d816Chong Zhang         * long period of suspension.
71694ee4b708acfa941581160b267afb79192b1d816Chong Zhang         */
71794ee4b708acfa941581160b267afb79192b1d816Chong Zhang
71894ee4b708acfa941581160b267afb79192b1d816Chong Zhang        int64_t originalTimeUs = timeUs;
71994ee4b708acfa941581160b267afb79192b1d816Chong Zhang        if (mPrevOriginalTimeUs >= 0ll) {
72094ee4b708acfa941581160b267afb79192b1d816Chong Zhang            if (originalTimeUs < mPrevOriginalTimeUs) {
72194ee4b708acfa941581160b267afb79192b1d816Chong Zhang                // Drop the frame if it's going backward in time. Bad timestamp
72294ee4b708acfa941581160b267afb79192b1d816Chong Zhang                // could disrupt encoder's rate control completely.
723b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang                ALOGW("Dropping frame that's going backward in time");
72494ee4b708acfa941581160b267afb79192b1d816Chong Zhang                return -1;
72594ee4b708acfa941581160b267afb79192b1d816Chong Zhang            }
72694ee4b708acfa941581160b267afb79192b1d816Chong Zhang            int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
72794ee4b708acfa941581160b267afb79192b1d816Chong Zhang            timeUs = (timestampGapUs < mMaxTimestampGapUs ?
72894ee4b708acfa941581160b267afb79192b1d816Chong Zhang                    timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
72994ee4b708acfa941581160b267afb79192b1d816Chong Zhang        }
73094ee4b708acfa941581160b267afb79192b1d816Chong Zhang        mPrevOriginalTimeUs = originalTimeUs;
73194ee4b708acfa941581160b267afb79192b1d816Chong Zhang        mPrevModifiedTimeUs = timeUs;
73294ee4b708acfa941581160b267afb79192b1d816Chong Zhang        mOriginalTimeUs.add(timeUs, originalTimeUs);
733a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("IN  timestamp: %lld -> %lld",
734a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            static_cast<long long>(originalTimeUs),
735a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn            static_cast<long long>(timeUs));
73694ee4b708acfa941581160b267afb79192b1d816Chong Zhang    }
73794ee4b708acfa941581160b267afb79192b1d816Chong Zhang
73894ee4b708acfa941581160b267afb79192b1d816Chong Zhang    return timeUs;
73994ee4b708acfa941581160b267afb79192b1d816Chong Zhang}
74094ee4b708acfa941581160b267afb79192b1d816Chong Zhang
74115ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnarstatus_t GraphicBufferSource::submitBuffer_l(const BufferItem &item, int cbi) {
742f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    ALOGV("submitBuffer_l cbi=%d", cbi);
743b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang
744b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang    int64_t timeUs = getTimestamp(item);
745b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang    if (timeUs < 0ll) {
746b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang        return UNKNOWN_ERROR;
747b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang    }
748b63d2433350d56bda9f3477549086c90bb6d535eChong Zhang
749f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
750d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf];
751d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mBuf = item.mBuf;
752d030447b617105b31bf3013e5e4b39d422b53b77Lajos Molnar    codecBuffer.mFrameNumber = item.mFrameNumber;
753f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
754f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
755054219874873b41f1c815552987c10465c34ba2bLajos Molnar    sp<GraphicBuffer> buffer = codecBuffer.mGraphicBuffer;
756054219874873b41f1c815552987c10465c34ba2bLajos Molnar    status_t err = mNodeInstance->emptyGraphicBuffer(
75715ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            header, buffer, OMX_BUFFERFLAG_ENDOFFRAME, timeUs,
75815ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            item.mFence->isValid() ? item.mFence->dup() : -1);
759f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
760054219874873b41f1c815552987c10465c34ba2bLajos Molnar        ALOGW("WARNING: emptyNativeWindowBuffer failed: 0x%x", err);
761f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        codecBuffer.mGraphicBuffer = NULL;
762f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return err;
763f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
764f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
765054219874873b41f1c815552987c10465c34ba2bLajos Molnar    ALOGV("emptyNativeWindowBuffer succeeded, h=%p p=%p buf=%p bufhandle=%p",
766054219874873b41f1c815552987c10465c34ba2bLajos Molnar            header, header->pBuffer, buffer->getNativeBuffer(), buffer->handle);
767f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return OK;
768f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
769f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
770f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::submitEndOfInputStream_l() {
771f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mEndOfStream);
772f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mEndOfStreamSent) {
773f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("EOS already sent");
774f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
775f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
776f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
777f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    int cbi = findAvailableCodecBuffer_l();
778f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (cbi < 0) {
779f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: no codec buffers available");
780f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
781f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
782f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
783f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // We reject any additional incoming graphic buffers, so there's no need
784f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as
785f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    // in-use.
786f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
787f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
788f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
789054219874873b41f1c815552987c10465c34ba2bLajos Molnar    status_t err = mNodeInstance->emptyGraphicBuffer(
790054219874873b41f1c815552987c10465c34ba2bLajos Molnar            header, NULL /* buffer */, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
79115ab4996019387f27a48b81cb4774c21502bc0e5Lajos Molnar            0 /* timestamp */, -1 /* fenceFd */);
792f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (err != OK) {
793f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
794f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    } else {
795f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d",
796f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden                header, cbi);
7970c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden        mEndOfStreamSent = true;
798f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
799f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
800f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
801f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findAvailableCodecBuffer_l() {
802f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    CHECK(mCodecBuffers.size() > 0);
803f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
804f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
805f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mGraphicBuffer == NULL) {
806f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
807f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
808f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
809f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
810f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
811f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
812f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenint GraphicBufferSource::findMatchingCodecBuffer_l(
813f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        const OMX_BUFFERHEADERTYPE* header) {
814f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
815f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (mCodecBuffers[i].mHeader == header) {
816f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            return i;
817f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
818f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
819f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    return -1;
820f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
821f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
8229700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang/*
8239700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang * Releases an acquired buffer back to the consumer for either persistent
8249700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang * or non-persistent surfaces.
8259700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang *
8269700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang * id: buffer slot to release (in persistent case the id might be changed)
8279700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang * frameNum: frame number of the frame being released
8289700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang * buffer: GraphicBuffer pointer to release (note this must not be & as we
8299700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang *         will clear the original mBufferSlot in persistent case)
8309700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang * fence: fence of the frame being released
8319700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang */
8329700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhangvoid GraphicBufferSource::releaseBuffer(
8339700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang        int &id, uint64_t frameNum,
8349700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang        const sp<GraphicBuffer> buffer, const sp<Fence> &fence) {
8359700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    if (mIsPersistent) {
8369700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang        mConsumer->detachBuffer(id);
8379700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang        mBufferSlot[id] = NULL;
8389700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang
839264bac95912efe121d6a60026612617f04f42966Lajos Molnar        if (mConsumer->attachBuffer(&id, buffer) == OK) {
840264bac95912efe121d6a60026612617f04f42966Lajos Molnar            mConsumer->releaseBuffer(
841264bac95912efe121d6a60026612617f04f42966Lajos Molnar                    id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
842264bac95912efe121d6a60026612617f04f42966Lajos Molnar        }
8439700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    } else {
8449700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang        mConsumer->releaseBuffer(
8459700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang                id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
8469700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    }
847264bac95912efe121d6a60026612617f04f42966Lajos Molnar    id = -1; // invalidate id
8489700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang    mNumBufferAcquired--;
8499700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang}
8509700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang
851f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
85204f101c35eaa90b1f95939afac30674ec1611e6fDan Stozavoid GraphicBufferSource::onFrameAvailable(const BufferItem& /*item*/) {
853f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock autoLock(mMutex);
854f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
855a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("onFrameAvailable exec=%d avail=%zu",
8560c37f9d1320bb87fd242f9425c67dacd6ce20112Andy McFadden            mExecuting, mNumFramesAvailable);
857f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
858e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber    if (mEndOfStream || mSuspended) {
859e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        if (mEndOfStream) {
860e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // This should only be possible if a new buffer was queued after
861e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            // EOS was signaled, i.e. the app is misbehaving.
862e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber
863e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGW("onFrameAvailable: EOS is set, ignoring frame");
864e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        } else {
865e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber            ALOGV("onFrameAvailable: suspended, ignoring frame");
866e40cda70eec141fa05cbcca1de420fdb22b98be6Andreas Huber        }
867f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
8688ed8ceda7cfe29e8417142ef460cd70060204459Dan Stoza        BufferItem item;
8695205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza        status_t err = mConsumer->acquireBuffer(&item, 0);
870f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if (err == OK) {
8719700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang            mNumBufferAcquired++;
8729700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang
87349270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang            // If this is the first time we're seeing this buffer, add it to our
87449270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang            // slot table.
87549270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang            if (item.mGraphicBuffer != NULL) {
8762c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang                ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mBuf);
87749270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang                mBufferSlot[item.mBuf] = item.mGraphicBuffer;
87849270665e7a20cd120724fc388da8b166ff0b4f1Chong Zhang            }
879d291c222357303b9611cab89d0c3b047584ef377Chong Zhang
8809700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang            releaseBuffer(item.mBuf, item.mFrameNumber,
8819700f5fe4b3becfe858cbf5aa7964296975081bbChong Zhang                    item.mGraphicBuffer, item.mFence);
882f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
883f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        return;
884f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
885f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
886f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    mNumFramesAvailable++;
887f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
888a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatBufferDeferred = false;
889a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    ++mRepeatLastFrameGeneration;
890a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
891f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    if (mExecuting) {
892f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        fillCodecBuffer_l();
893f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
894f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
895f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
896f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden// BufferQueue::ConsumerListener callback
897f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFaddenvoid GraphicBufferSource::onBuffersReleased() {
898f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    Mutex::Autolock lock(mMutex);
899f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
9002475264264b51a7592c5b2e4cd6cfdaddba16644Dan Stoza    uint64_t slotMask;
9015205977929c8a63d3bba026c6bd7b4cc1e236627Dan Stoza    if (mConsumer->getReleasedBuffers(&slotMask) != NO_ERROR) {
902f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        ALOGW("onBuffersReleased: unable to get released buffer set");
9032475264264b51a7592c5b2e4cd6cfdaddba16644Dan Stoza        slotMask = 0xffffffffffffffffULL;
904f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
905f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
9062475264264b51a7592c5b2e4cd6cfdaddba16644Dan Stoza    ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
907f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
908f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
909f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        if ((slotMask & 0x01) != 0) {
910f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden            mBufferSlot[i] = NULL;
911f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        }
912f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden        slotMask >>= 1;
913f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden    }
914f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}
915f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden
9168dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hall// BufferQueue::ConsumerListener callback
9178dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hallvoid GraphicBufferSource::onSidebandStreamChanged() {
9188dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hall    ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
9198dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hall}
9208dcc81a2fdb35905347cf7ef46d198afa7ae79cdJesse Hall
921a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huberstatus_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(
922a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        int64_t repeatAfterUs) {
923a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    Mutex::Autolock autoLock(mMutex);
924a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
925a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    if (mExecuting || repeatAfterUs <= 0ll) {
926a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        return INVALID_OPERATION;
927a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
928a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
929a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    mRepeatAfterUs = repeatAfterUs;
930a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
931a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    return OK;
932a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
933a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
93494ee4b708acfa941581160b267afb79192b1d816Chong Zhangstatus_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) {
93594ee4b708acfa941581160b267afb79192b1d816Chong Zhang    Mutex::Autolock autoLock(mMutex);
93694ee4b708acfa941581160b267afb79192b1d816Chong Zhang
93794ee4b708acfa941581160b267afb79192b1d816Chong Zhang    if (mExecuting || maxGapUs <= 0ll) {
93894ee4b708acfa941581160b267afb79192b1d816Chong Zhang        return INVALID_OPERATION;
93994ee4b708acfa941581160b267afb79192b1d816Chong Zhang    }
94094ee4b708acfa941581160b267afb79192b1d816Chong Zhang
94194ee4b708acfa941581160b267afb79192b1d816Chong Zhang    mMaxTimestampGapUs = maxGapUs;
94294ee4b708acfa941581160b267afb79192b1d816Chong Zhang
94394ee4b708acfa941581160b267afb79192b1d816Chong Zhang    return OK;
94494ee4b708acfa941581160b267afb79192b1d816Chong Zhang}
94572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
94637b2b389139ed638831e49708c947863eef631efRonghua Wustatus_t GraphicBufferSource::setMaxFps(float maxFps) {
94737b2b389139ed638831e49708c947863eef631efRonghua Wu    Mutex::Autolock autoLock(mMutex);
94837b2b389139ed638831e49708c947863eef631efRonghua Wu
94937b2b389139ed638831e49708c947863eef631efRonghua Wu    if (mExecuting) {
95037b2b389139ed638831e49708c947863eef631efRonghua Wu        return INVALID_OPERATION;
95137b2b389139ed638831e49708c947863eef631efRonghua Wu    }
95237b2b389139ed638831e49708c947863eef631efRonghua Wu
95337b2b389139ed638831e49708c947863eef631efRonghua Wu    mFrameDropper = new FrameDropper();
95437b2b389139ed638831e49708c947863eef631efRonghua Wu    status_t err = mFrameDropper->setMaxFrameRate(maxFps);
95537b2b389139ed638831e49708c947863eef631efRonghua Wu    if (err != OK) {
95637b2b389139ed638831e49708c947863eef631efRonghua Wu        mFrameDropper.clear();
95737b2b389139ed638831e49708c947863eef631efRonghua Wu        return err;
95837b2b389139ed638831e49708c947863eef631efRonghua Wu    }
95937b2b389139ed638831e49708c947863eef631efRonghua Wu
96037b2b389139ed638831e49708c947863eef631efRonghua Wu    return OK;
96137b2b389139ed638831e49708c947863eef631efRonghua Wu}
96237b2b389139ed638831e49708c947863eef631efRonghua Wu
96372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid GraphicBufferSource::setSkipFramesBeforeUs(int64_t skipFramesBeforeUs) {
96472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Mutex::Autolock autoLock(mMutex);
96572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
96672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mSkipFramesBeforeNs =
96772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll;
96872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
96972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9702c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhangstatus_t GraphicBufferSource::setTimeLapseUs(int64_t* data) {
9712c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    Mutex::Autolock autoLock(mMutex);
9722c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
9732c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    if (mExecuting || data[0] <= 0ll || data[1] <= 0ll) {
9742c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang        return INVALID_OPERATION;
9752c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    }
9762c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
9772c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mTimePerFrameUs = data[0];
9782c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    mTimePerCaptureUs = data[1];
9792c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
9802c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang    return OK;
9812c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang}
9822c9c8cba8562cc3a27532e4cd348912cc78d8d98Chong Zhang
983a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Hubervoid GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
984a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    switch (msg->what()) {
985a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        case kWhatRepeatLastFrame:
986a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        {
987a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            Mutex::Autolock autoLock(mMutex);
988a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
989a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            int32_t generation;
990a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            CHECK(msg->findInt32("generation", &generation));
991a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
992a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (generation != mRepeatLastFrameGeneration) {
993a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                // stale
994a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                break;
995a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
996a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
997a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (!mExecuting || mNumFramesAvailable > 0) {
998a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                break;
999a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
1000a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
100137b2b389139ed638831e49708c947863eef631efRonghua Wu            bool success = repeatLatestBuffer_l();
1002a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
1003a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            if (success) {
100437b2b389139ed638831e49708c947863eef631efRonghua Wu                ALOGV("repeatLatestBuffer_l SUCCESS");
1005a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            } else {
100637b2b389139ed638831e49708c947863eef631efRonghua Wu                ALOGV("repeatLatestBuffer_l FAILURE");
1007a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber                mRepeatBufferDeferred = true;
1008a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            }
1009a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            break;
1010a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        }
1011a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
1012a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber        default:
1013a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber            TRESPASS();
1014a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber    }
1015a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber}
1016a61285dcf1da8a2cf40c499ee3a7b9fc4d74ac58Andreas Huber
1017f779bb50d9746d9526541c3e6dcdf619cac941b7Andy McFadden}  // namespace android
1018