blob: 569420bd1a92c8670f09ea03ba942073c13fbe68 [file] [log] [blame]
Andy McFaddenf779bb52013-02-19 07:28:30 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mark Salyzyndb43b342014-04-04 14:47:28 -070017#include <inttypes.h>
18
Andy McFaddenf779bb52013-02-19 07:28:30 -080019#define LOG_TAG "GraphicBufferSource"
Yin-Chia Yehb3921122017-04-18 15:52:55 -070020//#define LOG_NDEBUG 0
Andy McFaddenf779bb52013-02-19 07:28:30 -080021#include <utils/Log.h>
22
Lajos Molnarb77d03b2016-03-03 14:02:17 -080023#define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h
24
Wonsik Kim82832ce2018-01-26 17:43:53 -080025#include <media/stagefright/bqhelper/GraphicBufferSource.h>
26#include <media/stagefright/bqhelper/FrameDropper.h>
Andy McFaddenf779bb52013-02-19 07:28:30 -080027#include <media/stagefright/foundation/ADebug.h>
Andreas Hubera61285d2013-07-31 13:50:42 -070028#include <media/stagefright/foundation/AMessage.h>
Lajos Molnarb77d03b2016-03-03 14:02:17 -080029#include <media/stagefright/foundation/ColorUtils.h>
Lajos Molnar43fb79a2017-04-06 14:27:17 -070030#include <media/stagefright/foundation/FileDescriptor.h>
Andy McFaddenf779bb52013-02-19 07:28:30 -080031
Pawin Vongmasaee9bde72019-09-11 09:59:08 -070032#include <android-base/properties.h>
Mathias Agopian5e1f08b2013-07-16 22:54:39 -070033#include <media/hardware/MetadataBufferType.h>
Andy McFaddenf779bb52013-02-19 07:28:30 -080034#include <ui/GraphicBuffer.h>
Dan Stoza8ed8ced2015-03-12 15:19:45 -070035#include <gui/BufferItem.h>
Chong Zhang0e4c08e2019-04-19 10:00:45 -070036#include <gui/BufferQueue.h>
37#include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
Chong Zhangc8ce1d82019-03-27 10:18:38 -070038#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
Chong Zhang0e4c08e2019-04-19 10:00:45 -070039#include <gui/IGraphicBufferProducer.h>
40#include <gui/IGraphicBufferConsumer.h>
Pawin Vongmasa255735a2017-07-19 11:24:56 -070041#include <media/hardware/HardwareAPI.h>
Andy McFaddenf779bb52013-02-19 07:28:30 -080042
Dan Stoza24752642014-04-09 16:10:53 -070043#include <inttypes.h>
44
Lajos Molnar43fb79a2017-04-06 14:27:17 -070045#include <functional>
46#include <memory>
Pawin Vongmasa22dc5082017-04-20 05:12:55 -070047#include <cmath>
Lajos Molnar43fb79a2017-04-06 14:27:17 -070048
Andy McFaddenf779bb52013-02-19 07:28:30 -080049namespace android {
50
Pawin Vongmasa40821622017-11-14 20:09:38 -080051namespace {
52// kTimestampFluctuation is an upper bound of timestamp fluctuation from the
53// source that GraphicBufferSource allows. The unit of kTimestampFluctuation is
54// frames. More specifically, GraphicBufferSource will drop a frame if
55//
56// expectedNewFrametimestamp - actualNewFrameTimestamp <
57// (0.5 - kTimestampFluctuation) * expectedtimePeriodBetweenFrames
58//
59// where
60// - expectedNewFrameTimestamp is the calculated ideal timestamp of the new
61// incoming frame
62// - actualNewFrameTimestamp is the timestamp received from the source
63// - expectedTimePeriodBetweenFrames is the ideal difference of the timestamps
64// of two adjacent frames
65//
66// See GraphicBufferSource::calculateCodecTimestamp_l() for more detail about
67// how kTimestampFluctuation is used.
68//
69// kTimestampFluctuation should be non-negative. A higher value causes a smaller
70// chance of dropping frames, but at the same time a higher bound on the
71// difference between the source timestamp and the interpreted (snapped)
72// timestamp.
73//
74// The value of 0.05 means that GraphicBufferSource expects the input timestamps
75// to fluctuate no more than 5% from the regular time period.
76//
77// TODO: Justify the choice of this value, or make it configurable.
78constexpr double kTimestampFluctuation = 0.05;
79}
80
Lajos Molnar43fb79a2017-04-06 14:27:17 -070081/**
82 * A copiable object managing a buffer in the buffer cache managed by the producer. This object
83 * holds a reference to the buffer, and maintains which buffer slot it belongs to (if any), and
84 * whether it is still in a buffer slot. It also maintains whether there are any outstanging acquire
85 * references to it (by buffers acquired from the slot) mainly so that we can keep a debug
86 * count of how many buffers we need to still release back to the producer.
87 */
88struct GraphicBufferSource::CachedBuffer {
89 /**
90 * Token that is used to track acquire counts (as opposed to all references to this object).
91 */
92 struct Acquirable { };
93
94 /**
95 * Create using a buffer cached in a slot.
96 */
97 CachedBuffer(slot_id slot, const sp<GraphicBuffer> &graphicBuffer)
98 : mIsCached(true),
99 mSlot(slot),
100 mGraphicBuffer(graphicBuffer),
101 mAcquirable(std::make_shared<Acquirable>()) {
102 }
103
104 /**
105 * Returns the cache slot that this buffer is cached in, or -1 if it is no longer cached.
106 *
107 * This assumes that -1 slot id is invalid; though, it is just a benign collision used for
108 * debugging. This object explicitly manages whether it is still cached.
109 */
110 slot_id getSlot() const {
111 return mIsCached ? mSlot : -1;
112 }
113
114 /**
115 * Returns the cached buffer.
116 */
117 sp<GraphicBuffer> getGraphicBuffer() const {
118 return mGraphicBuffer;
119 }
120
121 /**
122 * Checks whether this buffer is still in the buffer cache.
123 */
124 bool isCached() const {
125 return mIsCached;
126 }
127
128 /**
129 * Checks whether this buffer has an acquired reference.
130 */
131 bool isAcquired() const {
132 return mAcquirable.use_count() > 1;
133 }
134
135 /**
136 * Gets and returns a shared acquired reference.
137 */
138 std::shared_ptr<Acquirable> getAcquirable() {
139 return mAcquirable;
140 }
141
142private:
143 friend void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t);
144
145 /**
146 * This method to be called when the buffer is no longer in the buffer cache.
147 * Called from discardBufferAtSlotIndex_l.
148 */
149 void onDroppedFromCache() {
150 CHECK_DBG(mIsCached);
151 mIsCached = false;
152 }
153
154 bool mIsCached;
155 slot_id mSlot;
156 sp<GraphicBuffer> mGraphicBuffer;
157 std::shared_ptr<Acquirable> mAcquirable;
158};
159
160/**
161 * A copiable object managing a buffer acquired from the producer. This must always be a cached
162 * buffer. This objects also manages its acquire fence and any release fences that may be returned
163 * by the encoder for this buffer (this buffer may be queued to the encoder multiple times).
164 * If no release fences are added by the encoder, the acquire fence is returned as the release
165 * fence for this - as it is assumed that noone waited for the acquire fence. Otherwise, it is
166 * assumed that the encoder has waited for the acquire fence (or returned it as the release
167 * fence).
168 */
169struct GraphicBufferSource::AcquiredBuffer {
170 AcquiredBuffer(
171 const std::shared_ptr<CachedBuffer> &buffer,
172 std::function<void(AcquiredBuffer *)> onReleased,
173 const sp<Fence> &acquireFence)
174 : mBuffer(buffer),
175 mAcquirable(buffer->getAcquirable()),
176 mAcquireFence(acquireFence),
177 mGotReleaseFences(false),
178 mOnReleased(onReleased) {
179 }
180
181 /**
182 * Adds a release fence returned by the encoder to this object. If this is called with an
183 * valid file descriptor, it is added to the list of release fences. These are returned to the
184 * producer on release() as a merged fence. Regardless of the validity of the file descriptor,
185 * we take note that a release fence was attempted to be added and the acquire fence can now be
186 * assumed as acquired.
187 */
188 void addReleaseFenceFd(int fenceFd) {
189 // save all release fences - these will be propagated to the producer if this buffer is
190 // ever released to it
191 if (fenceFd >= 0) {
192 mReleaseFenceFds.push_back(fenceFd);
193 }
194 mGotReleaseFences = true;
195 }
196
197 /**
198 * Returns the acquire fence file descriptor associated with this object.
199 */
200 int getAcquireFenceFd() {
201 if (mAcquireFence == nullptr || !mAcquireFence->isValid()) {
202 return -1;
203 }
204 return mAcquireFence->dup();
205 }
206
207 /**
208 * Returns whether the buffer is still in the buffer cache.
209 */
210 bool isCached() const {
211 return mBuffer->isCached();
212 }
213
214 /**
215 * Returns the acquired buffer.
216 */
217 sp<GraphicBuffer> getGraphicBuffer() const {
218 return mBuffer->getGraphicBuffer();
219 }
220
221 /**
222 * Returns the slot that this buffer is cached at, or -1 otherwise.
223 *
224 * This assumes that -1 slot id is invalid; though, it is just a benign collision used for
225 * debugging. This object explicitly manages whether it is still cached.
226 */
227 slot_id getSlot() const {
228 return mBuffer->getSlot();
229 }
230
231 /**
232 * Creates and returns a release fence object from the acquire fence and/or any release fences
233 * added. If no release fences were added (even if invalid), returns the acquire fence.
234 * Otherwise, it returns a merged fence from all the valid release fences added.
235 */
236 sp<Fence> getReleaseFence() {
237 // If did not receive release fences, we assume this buffer was not consumed (it was
238 // discarded or dropped). In this case release the acquire fence as the release fence.
239 // We do this here to avoid a dup, close and recreation of the Fence object.
240 if (!mGotReleaseFences) {
241 return mAcquireFence;
242 }
243 sp<Fence> ret = getReleaseFence(0, mReleaseFenceFds.size());
244 // clear fds as fence took ownership of them
245 mReleaseFenceFds.clear();
246 return ret;
247 }
248
249 // this video buffer is no longer referenced by the codec (or kept for later encoding)
250 // it is now safe to release to the producer
251 ~AcquiredBuffer() {
252 //mAcquirable.clear();
253 mOnReleased(this);
254 // mOnRelease method should call getReleaseFence() that releases all fds but just in case
255 ALOGW_IF(!mReleaseFenceFds.empty(), "release fences were not obtained, closing fds");
256 for (int fildes : mReleaseFenceFds) {
257 ::close(fildes);
258 TRESPASS_DBG();
259 }
260 }
261
262private:
263 std::shared_ptr<GraphicBufferSource::CachedBuffer> mBuffer;
264 std::shared_ptr<GraphicBufferSource::CachedBuffer::Acquirable> mAcquirable;
265 sp<Fence> mAcquireFence;
266 Vector<int> mReleaseFenceFds;
267 bool mGotReleaseFences;
268 std::function<void(AcquiredBuffer *)> mOnReleased;
269
270 /**
271 * Creates and returns a release fence from 0 or more release fence file descriptors in from
272 * the specified range in the array.
273 *
274 * @param start start index
275 * @param num number of release fds to merge
276 */
277 sp<Fence> getReleaseFence(size_t start, size_t num) const {
278 if (num == 0) {
279 return Fence::NO_FENCE;
280 } else if (num == 1) {
281 return new Fence(mReleaseFenceFds[start]);
282 } else {
283 return Fence::merge("GBS::AB",
284 getReleaseFence(start, num >> 1),
285 getReleaseFence(start + (num >> 1), num - (num >> 1)));
286 }
287 }
288};
289
Chong Zhang0fe4c472019-04-08 21:51:46 +0000290struct GraphicBufferSource::ConsumerProxy : public BufferQueue::ConsumerListener {
Chong Zhang768fc2d2019-04-15 11:54:59 -0700291 ConsumerProxy(const wp<GraphicBufferSource> &gbs) : mGbs(gbs) {}
Chong Zhang0fe4c472019-04-08 21:51:46 +0000292
293 ~ConsumerProxy() = default;
294
295 void onFrameAvailable(const BufferItem& item) override {
Chong Zhang768fc2d2019-04-15 11:54:59 -0700296 sp<GraphicBufferSource> gbs = mGbs.promote();
297 if (gbs != nullptr) {
298 gbs->onFrameAvailable(item);
299 }
Chong Zhang0fe4c472019-04-08 21:51:46 +0000300 }
301
302 void onBuffersReleased() override {
Chong Zhang768fc2d2019-04-15 11:54:59 -0700303 sp<GraphicBufferSource> gbs = mGbs.promote();
304 if (gbs != nullptr) {
305 gbs->onBuffersReleased();
306 }
Chong Zhang0fe4c472019-04-08 21:51:46 +0000307 }
308
309 void onSidebandStreamChanged() override {
Chong Zhang768fc2d2019-04-15 11:54:59 -0700310 sp<GraphicBufferSource> gbs = mGbs.promote();
311 if (gbs != nullptr) {
312 gbs->onSidebandStreamChanged();
313 }
Chong Zhang0fe4c472019-04-08 21:51:46 +0000314 }
315
316private:
Chong Zhang768fc2d2019-04-15 11:54:59 -0700317 // Note that GraphicBufferSource is holding an sp to us, we can't hold
318 // an sp back to GraphicBufferSource as the circular dependency will
319 // make both immortal.
320 wp<GraphicBufferSource> mGbs;
Chong Zhang0fe4c472019-04-08 21:51:46 +0000321};
322
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700323GraphicBufferSource::GraphicBufferSource() :
Andy McFaddenf779bb52013-02-19 07:28:30 -0800324 mInitCheck(UNKNOWN_ERROR),
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700325 mNumAvailableUnacquiredBuffers(0),
326 mNumOutstandingAcquires(0),
327 mEndOfStream(false),
328 mEndOfStreamSent(false),
329 mLastDataspace(HAL_DATASPACE_UNKNOWN),
Andy McFaddenf779bb52013-02-19 07:28:30 -0800330 mExecuting(false),
Andreas Hubere40cda72013-07-17 13:55:26 -0700331 mSuspended(false),
Hangyu Kuangf72cefd2017-04-05 11:07:08 -0700332 mLastFrameTimestampUs(-1),
Hangyu Kuang764d9452016-12-13 13:07:45 -0800333 mStopTimeUs(-1),
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -0800334 mLastActionTimeUs(-1LL),
335 mSkipFramesBeforeNs(-1LL),
336 mFrameRepeatIntervalUs(-1LL),
Andreas Hubera61285d2013-07-31 13:50:42 -0700337 mRepeatLastFrameGeneration(0),
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700338 mOutstandingFrameRepeatCount(0),
339 mFrameRepeatBlockedOnCodecBuffer(false),
Pawin Vongmasa22dc5082017-04-20 05:12:55 -0700340 mFps(-1.0),
341 mCaptureFps(-1.0),
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -0800342 mBaseCaptureUs(-1LL),
343 mBaseFrameUs(-1LL),
Pawin Vongmasa22dc5082017-04-20 05:12:55 -0700344 mFrameCount(0),
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -0800345 mPrevCaptureUs(-1LL),
346 mPrevFrameUs(-1LL),
347 mInputBufferTimeOffsetUs(0LL) {
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700348 ALOGV("GraphicBufferSource");
Andy McFaddenf779bb52013-02-19 07:28:30 -0800349
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700350 String8 name("GraphicBufferSource");
Andy McFaddenf779bb52013-02-19 07:28:30 -0800351
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700352 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
353 mConsumer->setConsumerName(name);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800354
Chong Zhang0fe4c472019-04-08 21:51:46 +0000355 // create the consumer listener interface, and hold sp so that this
356 // interface lives as long as the GraphicBufferSource.
357 mConsumerProxy = new ConsumerProxy(this);
358
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700359 sp<IConsumerListener> proxy =
Chong Zhang0fe4c472019-04-08 21:51:46 +0000360 new BufferQueue::ProxyConsumerListener(mConsumerProxy);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800361
Dan Stoza52059772014-03-12 15:07:30 -0700362 mInitCheck = mConsumer->consumerConnect(proxy, false);
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700363 if (mInitCheck != NO_ERROR) {
Andy McFaddenf779bb52013-02-19 07:28:30 -0800364 ALOGE("Error connecting to BufferQueue: %s (%d)",
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700365 strerror(-mInitCheck), mInitCheck);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800366 return;
367 }
368
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700369 memset(&mDefaultColorAspectsPacked, 0, sizeof(mDefaultColorAspectsPacked));
Lajos Molnardd81af72016-03-10 18:19:18 -0800370
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700371 CHECK(mInitCheck == NO_ERROR);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800372}
373
374GraphicBufferSource::~GraphicBufferSource() {
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700375 ALOGV("~GraphicBufferSource");
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700376 {
377 // all acquired buffers must be freed with the mutex locked otherwise our debug assertion
378 // may trigger
379 Mutex::Autolock autoLock(mMutex);
380 mAvailableBuffers.clear();
381 mSubmittedCodecBuffers.clear();
382 mLatestBuffer.mBuffer.reset();
Chong Zhang9700f5f2015-06-12 18:30:08 -0700383 }
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700384
385 if (mNumOutstandingAcquires != 0) {
386 ALOGW("potential buffer leak: acquired=%d", mNumOutstandingAcquires);
387 TRESPASS_DBG();
Chong Zhang9700f5f2015-06-12 18:30:08 -0700388 }
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700389 if (mConsumer != NULL) {
Dan Stoza52059772014-03-12 15:07:30 -0700390 status_t err = mConsumer->consumerDisconnect();
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700391 if (err != NO_ERROR) {
392 ALOGW("consumerDisconnect failed: %d", err);
393 }
Andy McFaddenf779bb52013-02-19 07:28:30 -0800394 }
395}
396
Chong Zhang0e4c08e2019-04-19 10:00:45 -0700397sp<IGraphicBufferProducer> GraphicBufferSource::getIGraphicBufferProducer() const {
398 return mProducer;
399}
400
401sp<::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>
402GraphicBufferSource::getHGraphicBufferProducer_V1_0() const {
403 using TWGraphicBufferProducer = ::android::TWGraphicBufferProducer<
404 ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>;
405
406 return new TWGraphicBufferProducer(getIGraphicBufferProducer());
407}
408
Chong Zhangc8ce1d82019-03-27 10:18:38 -0700409sp<::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer>
410GraphicBufferSource::getHGraphicBufferProducer() const {
411 return new ::android::hardware::graphics::bufferqueue::V2_0::utils::
412 B2HGraphicBufferProducer(getIGraphicBufferProducer());
413}
414
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800415status_t GraphicBufferSource::start() {
Andy McFaddenf779bb52013-02-19 07:28:30 -0800416 Mutex::Autolock autoLock(mMutex);
Wonsik Kim28605732018-01-11 17:11:11 -0800417 ALOGV("--> start; available=%zu, submittable=%zd",
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700418 mAvailableBuffers.size(), mFreeCodecBuffers.size());
Andy McFaddenf779bb52013-02-19 07:28:30 -0800419 CHECK(!mExecuting);
420 mExecuting = true;
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700421 mLastDataspace = HAL_DATASPACE_UNKNOWN;
Lajos Molnarb77d03b2016-03-03 14:02:17 -0800422 ALOGV("clearing last dataSpace");
Andy McFaddenf779bb52013-02-19 07:28:30 -0800423
424 // Start by loading up as many buffers as possible. We want to do this,
425 // rather than just submit the first buffer, to avoid a degenerate case:
426 // if all BQ buffers arrive before we start executing, and we only submit
427 // one here, the other BQ buffers will just sit until we get notified
428 // that the codec buffer has been released. We'd then acquire and
429 // submit a single additional buffer, repeatedly, never using more than
430 // one codec buffer simultaneously. (We could instead try to submit
431 // all BQ buffers whenever any codec buffer is freed, but if we get the
432 // initial conditions right that will never be useful.)
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700433 while (haveAvailableBuffers_l()) {
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700434 if (!fillCodecBuffer_l()) {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700435 ALOGV("stop load with available=%zu+%d",
436 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700437 break;
438 }
Andy McFaddenf779bb52013-02-19 07:28:30 -0800439 }
440
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700441 ALOGV("done loading initial frames, available=%zu+%d",
442 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800443
444 // If EOS has already been signaled, and there are no more frames to
445 // submit, try to send EOS now as well.
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700446 if (mStopTimeUs == -1 && mEndOfStream && !haveAvailableBuffers_l()) {
Andy McFaddenf779bb52013-02-19 07:28:30 -0800447 submitEndOfInputStream_l();
448 }
Andreas Hubera61285d2013-07-31 13:50:42 -0700449
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -0800450 if (mFrameRepeatIntervalUs > 0LL && mLooper == NULL) {
Andreas Hubera61285d2013-07-31 13:50:42 -0700451 mReflector = new AHandlerReflector<GraphicBufferSource>(this);
452
453 mLooper = new ALooper;
454 mLooper->registerHandler(mReflector);
455 mLooper->start();
456
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700457 if (mLatestBuffer.mBuffer != nullptr) {
458 queueFrameRepeat_l();
Andreas Hubera61285d2013-07-31 13:50:42 -0700459 }
460 }
Chong Zhang6d332d22016-09-07 12:06:50 -0700461
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800462 return OK;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800463}
464
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800465status_t GraphicBufferSource::stop() {
Wonsik Kim28605732018-01-11 17:11:11 -0800466 ALOGV("stop");
Andreas Huberad3b7e82013-11-07 11:13:27 -0800467
468 Mutex::Autolock autoLock(mMutex);
469
470 if (mExecuting) {
471 // We are only interested in the transition from executing->idle,
472 // not loaded->idle.
Andreas Huber892e1b92013-11-08 10:57:34 -0800473 mExecuting = false;
Andreas Huberad3b7e82013-11-07 11:13:27 -0800474 }
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800475 return OK;
Andreas Huberad3b7e82013-11-07 11:13:27 -0800476}
477
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800478status_t GraphicBufferSource::release(){
Pawin Vongmasa2b0ee672018-03-08 16:19:07 -0800479 sp<ALooper> looper;
480 {
481 Mutex::Autolock autoLock(mMutex);
482 looper = mLooper;
483 if (mLooper != NULL) {
484 mLooper->unregisterHandler(mReflector->id());
485 mReflector.clear();
Andreas Hubera61285d2013-07-31 13:50:42 -0700486
Pawin Vongmasa2b0ee672018-03-08 16:19:07 -0800487 mLooper.clear();
488 }
489
490 ALOGV("--> release; available=%zu+%d eos=%d eosSent=%d acquired=%d",
491 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers,
492 mEndOfStream, mEndOfStreamSent, mNumOutstandingAcquires);
493
494 // Codec is no longer executing. Releasing all buffers to bq.
495 mFreeCodecBuffers.clear();
496 mSubmittedCodecBuffers.clear();
497 mLatestBuffer.mBuffer.reset();
498 mComponent.clear();
499 mExecuting = false;
Andreas Hubera61285d2013-07-31 13:50:42 -0700500 }
Pawin Vongmasa2b0ee672018-03-08 16:19:07 -0800501 if (looper != NULL) {
502 looper->stop();
503 }
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800504 return OK;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800505}
506
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800507status_t GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) {
Andy McFaddenf779bb52013-02-19 07:28:30 -0800508 Mutex::Autolock autoLock(mMutex);
509
510 if (mExecuting) {
511 // This should never happen -- buffers can only be allocated when
512 // transitioning from "loaded" to "idle".
513 ALOGE("addCodecBuffer: buffer added while executing");
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800514 return INVALID_OPERATION;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800515 }
516
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700517 ALOGV("addCodecBuffer: bufferId=%u", bufferId);
Chong Zhang6cf9a122016-09-08 23:25:52 -0700518
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700519 mFreeCodecBuffers.push_back(bufferId);
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800520 return OK;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800521}
522
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800523status_t GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) {
Andy McFaddenf779bb52013-02-19 07:28:30 -0800524 Mutex::Autolock autoLock(mMutex);
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700525 FileDescriptor::Autoclose fence(fenceFd);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800526
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700527 ssize_t cbi = mSubmittedCodecBuffers.indexOfKey(bufferId);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800528 if (cbi < 0) {
529 // This should never happen.
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700530 ALOGE("onInputBufferEmptied: buffer not recognized (bufferId=%u)", bufferId);
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800531 return BAD_VALUE;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800532 }
533
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700534 std::shared_ptr<AcquiredBuffer> buffer = mSubmittedCodecBuffers.valueAt(cbi);
535
536 // Move buffer to available buffers
537 mSubmittedCodecBuffers.removeItemsAt(cbi);
538 mFreeCodecBuffers.push_back(bufferId);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800539
540 // header->nFilledLen may not be the original value, so we can't compare
541 // that to zero to see of this was the EOS buffer. Instead we just
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700542 // see if there is a null AcquiredBuffer, which should only ever happen for EOS.
543 if (buffer == nullptr) {
Andy McFadden5572b3a2013-11-07 14:39:03 -0800544 if (!(mEndOfStream && mEndOfStreamSent)) {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700545 // This can happen when broken code sends us the same buffer twice in a row.
546 ALOGE("onInputBufferEmptied: non-EOS null buffer (bufferId=%u)", bufferId);
547 } else {
548 ALOGV("onInputBufferEmptied: EOS null buffer (bufferId=%u@%zd)", bufferId, cbi);
Andy McFadden5572b3a2013-11-07 14:39:03 -0800549 }
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700550 // No GraphicBuffer to deal with, no additional input or output is expected, so just return.
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800551 return BAD_VALUE;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800552 }
553
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700554 if (!mExecuting) {
555 // this is fine since this could happen when going from Idle to Loaded
556 ALOGV("onInputBufferEmptied: no longer executing (bufferId=%u@%zd)", bufferId, cbi);
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800557 return OK;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800558 }
559
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700560 ALOGV("onInputBufferEmptied: bufferId=%d@%zd [slot=%d, useCount=%ld, handle=%p] acquired=%d",
561 bufferId, cbi, buffer->getSlot(), buffer.use_count(), buffer->getGraphicBuffer()->handle,
562 mNumOutstandingAcquires);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800563
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700564 buffer->addReleaseFenceFd(fence.release());
565 // release codec reference for video buffer just in case remove does not it
566 buffer.reset();
567
568 if (haveAvailableBuffers_l()) {
Andy McFaddenf779bb52013-02-19 07:28:30 -0800569 // Fill this codec buffer.
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700570 CHECK(!mEndOfStreamSent);
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700571 ALOGV("onInputBufferEmptied: buffer freed, feeding codec (available=%zu+%d, eos=%d)",
572 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800573 fillCodecBuffer_l();
Hangyu Kuang764d9452016-12-13 13:07:45 -0800574 } else if (mEndOfStream && mStopTimeUs == -1) {
575 // No frames available, but EOS is pending and no stop time, so use this buffer to
Andy McFaddenf779bb52013-02-19 07:28:30 -0800576 // send that.
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700577 ALOGV("onInputBufferEmptied: buffer freed, submitting EOS");
Andy McFaddenf779bb52013-02-19 07:28:30 -0800578 submitEndOfInputStream_l();
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700579 } else if (mFrameRepeatBlockedOnCodecBuffer) {
Ronghua Wu37b2b382015-01-26 15:47:10 -0800580 bool success = repeatLatestBuffer_l();
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700581 ALOGV("onInputBufferEmptied: completing deferred repeatLatestBuffer_l %s",
582 success ? "SUCCESS" : "FAILURE");
583 mFrameRepeatBlockedOnCodecBuffer = false;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800584 }
Andreas Hubera61285d2013-07-31 13:50:42 -0700585
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700586 // releaseReleasableBuffers_l();
Chong Zhangd1bbbe32020-01-15 17:13:01 -0800587 return OK;
Andreas Hubere40cda72013-07-17 13:55:26 -0700588}
589
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700590void GraphicBufferSource::onDataspaceChanged_l(
591 android_dataspace dataspace, android_pixel_format pixelFormat) {
guochuangf677f7c2023-05-09 20:28:27 +0800592 ALOGD("got buffer with new dataSpace %#x", dataspace);
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700593 mLastDataspace = dataspace;
Lajos Molnarb77d03b2016-03-03 14:02:17 -0800594
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700595 if (ColorUtils::convertDataSpaceToV0(dataspace)) {
Wonsik Kim28605732018-01-11 17:11:11 -0800596 mComponent->dispatchDataSpaceChanged(
597 mLastDataspace, mDefaultColorAspectsPacked, pixelFormat);
Lajos Molnarb77d03b2016-03-03 14:02:17 -0800598 }
599}
600
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700601bool GraphicBufferSource::fillCodecBuffer_l() {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700602 CHECK(mExecuting && haveAvailableBuffers_l());
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700603
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700604 if (mFreeCodecBuffers.empty()) {
Andy McFaddenf779bb52013-02-19 07:28:30 -0800605 // No buffers available, bail.
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700606 ALOGV("fillCodecBuffer_l: no codec buffers, available=%zu+%d",
607 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700608 return false;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800609 }
610
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700611 VideoBuffer item;
612 if (mAvailableBuffers.empty()) {
613 ALOGV("fillCodecBuffer_l: acquiring available buffer, available=%zu+%d",
614 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
615 if (acquireBuffer_l(&item) != OK) {
616 ALOGE("fillCodecBuffer_l: failed to acquire available buffer");
617 return false;
618 }
619 } else {
620 ALOGV("fillCodecBuffer_l: getting available buffer, available=%zu+%d",
621 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
622 item = *mAvailableBuffers.begin();
623 mAvailableBuffers.erase(mAvailableBuffers.begin());
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700624 }
625
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700626 int64_t itemTimeUs = item.mTimestampNs / 1000;
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700627
Hangyu Kuang764d9452016-12-13 13:07:45 -0800628 // Process ActionItem in the Queue if there is any. If a buffer's timestamp
629 // is smaller than the first action's timestamp, no action need to be performed.
630 // If buffer's timestamp is larger or equal than the last action's timestamp,
631 // only the last action needs to be performed as all the acitions before the
632 // the action are overridden by the last action. For the other cases, traverse
633 // the Queue to find the newest action that with timestamp smaller or equal to
634 // the buffer's timestamp. For example, an action queue like
Hangyu Kuang384cd772017-03-20 16:15:37 -0700635 // [pause 1us], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon
Hangyu Kuang764d9452016-12-13 13:07:45 -0800636 // receiving a buffer with timestamp 3.5us, only the action [pause, 3us] needs
637 // to be handled and [pause, 1us], [resume 2us] will be discarded.
Hangyu Kuang764d9452016-12-13 13:07:45 -0800638 bool done = false;
Hangyu Kuang21bafd52017-03-30 12:39:38 -0700639 bool seeStopAction = false;
Hangyu Kuang764d9452016-12-13 13:07:45 -0800640 if (!mActionQueue.empty()) {
641 // First scan to check if bufferTimestamp is smaller than first action's timestamp.
642 ActionItem nextAction = *(mActionQueue.begin());
643 if (itemTimeUs < nextAction.mActionTimeUs) {
644 ALOGV("No action. buffer timestamp %lld us < action timestamp: %lld us",
645 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
646 // All the actions are ahead. No action need to perform now.
647 // Release the buffer if is in suspended state, or process the buffer
648 // if not in suspended state.
Hangyu Kuang764d9452016-12-13 13:07:45 -0800649 done = true;
650 }
651
652 if (!done) {
Hangyu Kuang384cd772017-03-20 16:15:37 -0700653 // Find the newest action that with timestamp smaller than itemTimeUs. Then
654 // remove all the actions before and include the newest action.
Hangyu Kuang764d9452016-12-13 13:07:45 -0800655 List<ActionItem>::iterator it = mActionQueue.begin();
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700656 while (it != mActionQueue.end() && it->mActionTimeUs <= itemTimeUs
657 && nextAction.mAction != ActionItem::STOP) {
Hangyu Kuang764d9452016-12-13 13:07:45 -0800658 nextAction = *it;
Hangyu Kuang764d9452016-12-13 13:07:45 -0800659 ++it;
660 }
Hangyu Kuang384cd772017-03-20 16:15:37 -0700661 mActionQueue.erase(mActionQueue.begin(), it);
Hangyu Kuang764d9452016-12-13 13:07:45 -0800662
663 CHECK(itemTimeUs >= nextAction.mActionTimeUs);
664 switch (nextAction.mAction) {
665 case ActionItem::PAUSE:
666 {
667 mSuspended = true;
Hangyu Kuang764d9452016-12-13 13:07:45 -0800668 ALOGV("RUNNING/PAUSE -> PAUSE at buffer %lld us PAUSE Time: %lld us",
669 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
670 break;
671 }
672 case ActionItem::RESUME:
673 {
674 mSuspended = false;
675 ALOGV("PAUSE/RUNNING -> RUNNING at buffer %lld us RESUME Time: %lld us",
676 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
677 break;
678 }
679 case ActionItem::STOP:
680 {
681 ALOGV("RUNNING/PAUSE -> STOP at buffer %lld us STOP Time: %lld us",
682 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
Hangyu Kuang764d9452016-12-13 13:07:45 -0800683 // Clear the whole ActionQueue as recording is done
684 mActionQueue.clear();
Hangyu Kuang21bafd52017-03-30 12:39:38 -0700685 seeStopAction = true;
Hangyu Kuang764d9452016-12-13 13:07:45 -0800686 break;
687 }
688 default:
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700689 TRESPASS_DBG("Unknown action type");
690 // return true here because we did consume an available buffer, so the
Wonsik Kim28605732018-01-11 17:11:11 -0800691 // loop in start will eventually terminate even if we hit this.
Hangyu Kuang764d9452016-12-13 13:07:45 -0800692 return false;
693 }
694 }
695 }
696
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700697 if (seeStopAction) {
698 // Clear all the buffers before setting mEndOfStream and signal EndOfInputStream.
699 releaseAllAvailableBuffers_l();
700 mEndOfStream = true;
701 submitEndOfInputStream_l();
Hangyu Kuang764d9452016-12-13 13:07:45 -0800702 return true;
703 }
704
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700705 if (mSuspended) {
706 return true;
Lajos Molnarb77d03b2016-03-03 14:02:17 -0800707 }
708
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700709 int err = UNKNOWN_ERROR;
Chong Zhang72cecca2013-12-26 01:38:35 -0800710
711 // only submit sample if start time is unspecified, or sample
712 // is queued after the specified start time
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -0800713 if (mSkipFramesBeforeNs < 0LL || item.mTimestampNs >= mSkipFramesBeforeNs) {
Chong Zhang72cecca2013-12-26 01:38:35 -0800714 // if start time is set, offset time stamp by start time
715 if (mSkipFramesBeforeNs > 0) {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700716 item.mTimestampNs -= mSkipFramesBeforeNs;
Chong Zhang72cecca2013-12-26 01:38:35 -0800717 }
Ronghua Wu37b2b382015-01-26 15:47:10 -0800718
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700719 int64_t timeUs = item.mTimestampNs / 1000;
Ronghua Wu37b2b382015-01-26 15:47:10 -0800720 if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) {
721 ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs));
722 // set err to OK so that the skipped frame can still be saved as the lastest frame
723 err = OK;
Ronghua Wu37b2b382015-01-26 15:47:10 -0800724 } else {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700725 err = submitBuffer_l(item); // this takes shared ownership of the acquired buffer on succeess
Ronghua Wu37b2b382015-01-26 15:47:10 -0800726 }
Chong Zhang72cecca2013-12-26 01:38:35 -0800727 }
728
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700729 if (err != OK) {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700730 ALOGV("submitBuffer_l failed, will release bq slot %d", item.mBuffer->getSlot());
731 return true;
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700732 } else {
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700733 // Don't set the last buffer id if we're not repeating,
734 // we'll be holding on to the last buffer for nothing.
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -0800735 if (mFrameRepeatIntervalUs > 0LL) {
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700736 setLatestBuffer_l(item);
737 }
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700738 ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d",
739 item.mBuffer->getSlot(), item.mBuffer.use_count(), mNumOutstandingAcquires);
Hangyu Kuangfd871c72017-04-28 10:11:19 -0700740 mLastFrameTimestampUs = itemTimeUs;
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700741 }
742
743 return true;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800744}
745
Ronghua Wu37b2b382015-01-26 15:47:10 -0800746bool GraphicBufferSource::repeatLatestBuffer_l() {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700747 CHECK(mExecuting && !haveAvailableBuffers_l());
Andreas Hubera61285d2013-07-31 13:50:42 -0700748
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700749 if (mLatestBuffer.mBuffer == nullptr || mSuspended) {
Andy McFaddenbdfd4882013-10-23 13:39:43 -0700750 return false;
751 }
Andreas Hubera61285d2013-07-31 13:50:42 -0700752
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700753 if (mFreeCodecBuffers.empty()) {
Andreas Hubera61285d2013-07-31 13:50:42 -0700754 // No buffers available, bail.
Ronghua Wu37b2b382015-01-26 15:47:10 -0800755 ALOGV("repeatLatestBuffer_l: no codec buffers.");
Andreas Hubera61285d2013-07-31 13:50:42 -0700756 return false;
757 }
758
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700759 if (!mLatestBuffer.mBuffer->isCached()) {
760 ALOGV("repeatLatestBuffer_l: slot was discarded, but repeating our own reference");
761 }
Andreas Hubera61285d2013-07-31 13:50:42 -0700762
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700763 // it is ok to update the timestamp of latest buffer as it is only used for submission
764 status_t err = submitBuffer_l(mLatestBuffer);
Andreas Hubera61285d2013-07-31 13:50:42 -0700765 if (err != OK) {
766 return false;
767 }
768
Chong Zhang94ee4b72014-01-10 17:36:57 -0800769 /* repeat last frame up to kRepeatLastFrameCount times.
770 * in case of static scene, a single repeat might not get rid of encoder
771 * ghosting completely, refresh a couple more times to get better quality
772 */
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700773 if (--mOutstandingFrameRepeatCount > 0) {
774 // set up timestamp for repeat frame
775 mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000;
776 queueFrameRepeat_l();
Chong Zhang94ee4b72014-01-10 17:36:57 -0800777 }
778
Andreas Hubera61285d2013-07-31 13:50:42 -0700779 return true;
780}
781
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700782void GraphicBufferSource::setLatestBuffer_l(const VideoBuffer &item) {
783 mLatestBuffer = item;
Andreas Hubera61285d2013-07-31 13:50:42 -0700784
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700785 ALOGV("setLatestBuffer_l: [slot=%d, useCount=%ld]",
786 mLatestBuffer.mBuffer->getSlot(), mLatestBuffer.mBuffer.use_count());
Chong Zhang94ee4b72014-01-10 17:36:57 -0800787
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700788 mOutstandingFrameRepeatCount = kRepeatLastFrameCount;
789 // set up timestamp for repeat frame
790 mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000;
791 queueFrameRepeat_l();
792}
Chong Zhangfdeac6c2016-09-14 17:57:57 -0700793
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700794void GraphicBufferSource::queueFrameRepeat_l() {
795 mFrameRepeatBlockedOnCodecBuffer = false;
Andreas Hubera61285d2013-07-31 13:50:42 -0700796
797 if (mReflector != NULL) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800798 sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
Andreas Hubera61285d2013-07-31 13:50:42 -0700799 msg->setInt32("generation", ++mRepeatLastFrameGeneration);
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700800 msg->post(mFrameRepeatIntervalUs);
Andreas Hubera61285d2013-07-31 13:50:42 -0700801 }
802}
803
Pawin Vongmasaee9bde72019-09-11 09:59:08 -0700804#ifdef __clang__
805__attribute__((no_sanitize("integer")))
806#endif
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700807bool GraphicBufferSource::calculateCodecTimestamp_l(
808 nsecs_t bufferTimeNs, int64_t *codecTimeUs) {
809 int64_t timeUs = bufferTimeNs / 1000;
Hangyu Kuang61fcfd12016-08-30 13:50:58 -0700810 timeUs += mInputBufferTimeOffsetUs;
Chong Zhang94ee4b72014-01-10 17:36:57 -0800811
Pawin Vongmasa22dc5082017-04-20 05:12:55 -0700812 if (mCaptureFps > 0.
813 && (mFps > 2 * mCaptureFps
814 || mCaptureFps > 2 * mFps)) {
Chong Zhang2c9c8cb2014-02-11 13:54:59 -0800815 // Time lapse or slow motion mode
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -0800816 if (mPrevCaptureUs < 0LL) {
Chong Zhang2c9c8cb2014-02-11 13:54:59 -0800817 // first capture
Pawin Vongmasa22dc5082017-04-20 05:12:55 -0700818 mPrevCaptureUs = mBaseCaptureUs = timeUs;
Hangyu Kuangbd83e4b2016-10-26 13:56:11 -0700819 // adjust the first sample timestamp.
Pawin Vongmasa22dc5082017-04-20 05:12:55 -0700820 mPrevFrameUs = mBaseFrameUs =
821 std::llround((timeUs * mCaptureFps) / mFps);
822 mFrameCount = 0;
Pawin Vongmasaee9bde72019-09-11 09:59:08 -0700823 } else if (mSnapTimestamps) {
Pawin Vongmasa40821622017-11-14 20:09:38 -0800824 double nFrames = (timeUs - mPrevCaptureUs) * mCaptureFps / 1000000;
825 if (nFrames < 0.5 - kTimestampFluctuation) {
Chong Zhang2c9c8cb2014-02-11 13:54:59 -0800826 // skip this frame as it's too close to previous capture
Pawin Vongmasaee9bde72019-09-11 09:59:08 -0700827 ALOGD("skipping frame, timeUs %lld",
828 static_cast<long long>(timeUs));
Chong Zhang6d332d22016-09-07 12:06:50 -0700829 return false;
Chong Zhang2c9c8cb2014-02-11 13:54:59 -0800830 }
Pawin Vongmasaee9bde72019-09-11 09:59:08 -0700831 // snap to nearest capture point
Pawin Vongmasa40821622017-11-14 20:09:38 -0800832 if (nFrames <= 1.0) {
833 nFrames = 1.0;
834 }
835 mFrameCount += std::llround(nFrames);
Pawin Vongmasa22dc5082017-04-20 05:12:55 -0700836 mPrevCaptureUs = mBaseCaptureUs + std::llround(
Pawin Vongmasa780882d2017-08-16 03:47:16 -0700837 mFrameCount * 1000000 / mCaptureFps);
Pawin Vongmasa22dc5082017-04-20 05:12:55 -0700838 mPrevFrameUs = mBaseFrameUs + std::llround(
Pawin Vongmasa780882d2017-08-16 03:47:16 -0700839 mFrameCount * 1000000 / mFps);
Pawin Vongmasaee9bde72019-09-11 09:59:08 -0700840 } else {
841 if (timeUs <= mPrevCaptureUs) {
842 if (mFrameDropper != NULL && mFrameDropper->disabled()) {
843 // Warn only, client has disabled frame drop logic possibly for image
844 // encoding cases where camera's ZSL mode could send out of order frames.
845 ALOGW("Received frame that's going backward in time");
846 } else {
847 // Drop the frame if it's going backward in time. Bad timestamp
848 // could disrupt encoder's rate control completely.
849 ALOGW("Dropping frame that's going backward in time");
850 return false;
851 }
852 }
853 mPrevCaptureUs = timeUs;
854 mPrevFrameUs = mBaseFrameUs + std::llround(
855 (timeUs - mBaseCaptureUs) * (mCaptureFps / mFps));
Chong Zhang2c9c8cb2014-02-11 13:54:59 -0800856 }
857
858 ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
Mark Salyzyna5750e02014-06-18 16:34:45 -0700859 static_cast<long long>(timeUs),
860 static_cast<long long>(mPrevCaptureUs),
861 static_cast<long long>(mPrevFrameUs));
Hangyu Kuang61fcfd12016-08-30 13:50:58 -0700862 } else {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700863 if (timeUs <= mPrevFrameUs) {
Chong Zhang6c2d0ad2018-05-24 19:36:53 -0700864 if (mFrameDropper != NULL && mFrameDropper->disabled()) {
865 // Warn only, client has disabled frame drop logic possibly for image
866 // encoding cases where camera's ZSL mode could send out of order frames.
867 ALOGW("Received frame that's going backward in time");
868 } else {
869 // Drop the frame if it's going backward in time. Bad timestamp
870 // could disrupt encoder's rate control completely.
871 ALOGW("Dropping frame that's going backward in time");
872 return false;
873 }
Chong Zhang94ee4b72014-01-10 17:36:57 -0800874 }
Hangyu Kuang61fcfd12016-08-30 13:50:58 -0700875
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700876 mPrevFrameUs = timeUs;
Chong Zhang94ee4b72014-01-10 17:36:57 -0800877 }
878
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700879 *codecTimeUs = mPrevFrameUs;
Chong Zhang6d332d22016-09-07 12:06:50 -0700880 return true;
Chong Zhang94ee4b72014-01-10 17:36:57 -0800881}
882
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700883status_t GraphicBufferSource::submitBuffer_l(const VideoBuffer &item) {
884 CHECK(!mFreeCodecBuffers.empty());
Wonsik Kim28605732018-01-11 17:11:11 -0800885 uint32_t codecBufferId = *mFreeCodecBuffers.begin();
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700886
887 ALOGV("submitBuffer_l [slot=%d, bufferId=%d]", item.mBuffer->getSlot(), codecBufferId);
Chong Zhangb63d2432014-02-14 15:26:00 -0800888
Chong Zhang3604cb12016-10-10 12:08:11 -0700889 int64_t codecTimeUs;
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700890 if (!calculateCodecTimestamp_l(item.mTimestampNs, &codecTimeUs)) {
Chong Zhangb63d2432014-02-14 15:26:00 -0800891 return UNKNOWN_ERROR;
892 }
893
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700894 if ((android_dataspace)item.mDataspace != mLastDataspace) {
895 onDataspaceChanged_l(
896 item.mDataspace,
897 (android_pixel_format)item.mBuffer->getGraphicBuffer()->format);
898 }
Andy McFaddenf779bb52013-02-19 07:28:30 -0800899
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700900 std::shared_ptr<AcquiredBuffer> buffer = item.mBuffer;
Wonsik Kim28605732018-01-11 17:11:11 -0800901 // use a GraphicBuffer for now as component is using GraphicBuffers to hold references
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700902 // and it requires this graphic buffer to be able to hold its reference
903 // and thus we would need to create a new GraphicBuffer from an ANWBuffer separate from the
904 // acquired GraphicBuffer.
905 // TODO: this can be reworked globally to use ANWBuffer references
906 sp<GraphicBuffer> graphicBuffer = buffer->getGraphicBuffer();
Wonsik Kim28605732018-01-11 17:11:11 -0800907 status_t err = mComponent->submitBuffer(
908 codecBufferId, graphicBuffer, codecTimeUs, buffer->getAcquireFenceFd());
Chong Zhang6cf9a122016-09-08 23:25:52 -0700909
Andy McFaddenf779bb52013-02-19 07:28:30 -0800910 if (err != OK) {
Chong Zhang6cf9a122016-09-08 23:25:52 -0700911 ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800912 return err;
913 }
914
Lajos Molnar195f1ed2017-04-26 15:19:47 -0700915 mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
916
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700917 ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, buffer);
918 ALOGV("emptyGraphicBuffer succeeded, bufferId=%u@%zd bufhandle=%p",
919 codecBufferId, cbix, graphicBuffer->handle);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800920 return OK;
921}
922
923void GraphicBufferSource::submitEndOfInputStream_l() {
924 CHECK(mEndOfStream);
925 if (mEndOfStreamSent) {
926 ALOGV("EOS already sent");
927 return;
928 }
929
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700930 if (mFreeCodecBuffers.empty()) {
Andy McFaddenf779bb52013-02-19 07:28:30 -0800931 ALOGV("submitEndOfInputStream_l: no codec buffers available");
932 return;
933 }
Wonsik Kim28605732018-01-11 17:11:11 -0800934 uint32_t codecBufferId = *mFreeCodecBuffers.begin();
Andy McFaddenf779bb52013-02-19 07:28:30 -0800935
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700936 // We reject any additional incoming graphic buffers. There is no acquired buffer used for EOS
Wonsik Kim28605732018-01-11 17:11:11 -0800937 status_t err = mComponent->submitEos(codecBufferId);
Andy McFaddenf779bb52013-02-19 07:28:30 -0800938 if (err != OK) {
939 ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
940 } else {
Lajos Molnar195f1ed2017-04-26 15:19:47 -0700941 mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700942 ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, nullptr);
943 ALOGV("submitEndOfInputStream_l: buffer submitted, bufferId=%u@%zd", codecBufferId, cbix);
Andy McFadden0c37f9d2013-03-11 15:09:32 -0700944 mEndOfStreamSent = true;
Lajos Molnar1f0fa902017-06-05 12:42:17 -0700945
946 // no need to hold onto any buffers for frame repeating
947 ++mRepeatLastFrameGeneration;
948 mLatestBuffer.mBuffer.reset();
Andy McFaddenf779bb52013-02-19 07:28:30 -0800949 }
950}
951
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700952status_t GraphicBufferSource::acquireBuffer_l(VideoBuffer *ab) {
953 BufferItem bi;
954 status_t err = mConsumer->acquireBuffer(&bi, 0);
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700955 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
956 // shouldn't happen
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700957 ALOGW("acquireBuffer_l: frame was not available");
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700958 return err;
959 } else if (err != OK) {
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700960 ALOGW("acquireBuffer_l: failed with err=%d", err);
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700961 return err;
962 }
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700963 --mNumAvailableUnacquiredBuffers;
964
965 // Manage our buffer cache.
966 std::shared_ptr<CachedBuffer> buffer;
967 ssize_t bsi = mBufferSlots.indexOfKey(bi.mSlot);
968 if (bi.mGraphicBuffer != NULL) {
969 // replace/initialize slot with new buffer
970 ALOGV("acquireBuffer_l: %s buffer slot %d", bsi < 0 ? "setting" : "UPDATING", bi.mSlot);
971 if (bsi >= 0) {
972 discardBufferAtSlotIndex_l(bsi);
973 } else {
974 bsi = mBufferSlots.add(bi.mSlot, nullptr);
975 }
976 buffer = std::make_shared<CachedBuffer>(bi.mSlot, bi.mGraphicBuffer);
977 mBufferSlots.replaceValueAt(bsi, buffer);
978 } else {
979 buffer = mBufferSlots.valueAt(bsi);
Chong Zhangaddf2cb2016-09-28 17:53:01 -0700980 }
Lajos Molnar43fb79a2017-04-06 14:27:17 -0700981 int64_t frameNum = bi.mFrameNumber;
982
983 std::shared_ptr<AcquiredBuffer> acquiredBuffer =
984 std::make_shared<AcquiredBuffer>(
985 buffer,
986 [frameNum, this](AcquiredBuffer *buffer){
987 // AcquiredBuffer's destructor should always be called when mMutex is locked.
988 // If we had a reentrant mutex, we could just lock it again to ensure this.
989 if (mMutex.tryLock() == 0) {
990 TRESPASS_DBG();
991 mMutex.unlock();
992 }
993
994 // we can release buffers immediately if not using adapters
995 // alternately, we could add them to mSlotsToRelease, but we would
996 // somehow need to propagate frame number to that queue
997 if (buffer->isCached()) {
998 --mNumOutstandingAcquires;
999 mConsumer->releaseBuffer(
1000 buffer->getSlot(), frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
1001 buffer->getReleaseFence());
1002 }
1003 },
1004 bi.mFence);
1005 VideoBuffer videoBuffer{acquiredBuffer, bi.mTimestamp, bi.mDataSpace};
1006 *ab = videoBuffer;
1007 ++mNumOutstandingAcquires;
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001008 return OK;
1009}
1010
Andy McFaddenf779bb52013-02-19 07:28:30 -08001011// BufferQueue::ConsumerListener callback
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001012void GraphicBufferSource::onFrameAvailable(const BufferItem& item __unused) {
Andy McFaddenf779bb52013-02-19 07:28:30 -08001013 Mutex::Autolock autoLock(mMutex);
1014
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001015 ALOGV("onFrameAvailable: executing=%d available=%zu+%d",
1016 mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
1017 ++mNumAvailableUnacquiredBuffers;
Andy McFaddenf779bb52013-02-19 07:28:30 -08001018
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001019 // For BufferQueue we cannot acquire a buffer if we cannot immediately feed it to the codec
Lajos Molnar02cccfd2017-04-25 18:08:42 -07001020 // UNLESS we are discarding this buffer (acquiring and immediately releasing it), which makes
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001021 // this an ugly logic.
1022 // NOTE: We could also rely on our debug counter but that is meant only as a debug counter.
1023 if (!areWeDiscardingAvailableBuffers_l() && mFreeCodecBuffers.empty()) {
1024 // we may not be allowed to acquire a possibly encodable buffer, so just note that
1025 // it is available
1026 ALOGV("onFrameAvailable: cannot acquire buffer right now, do it later");
Andreas Hubere40cda72013-07-17 13:55:26 -07001027
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001028 ++mRepeatLastFrameGeneration; // cancel any pending frame repeat
Lajos Molnar02cccfd2017-04-25 18:08:42 -07001029 return;
Andy McFaddenf779bb52013-02-19 07:28:30 -08001030 }
1031
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001032 VideoBuffer buffer;
1033 status_t err = acquireBuffer_l(&buffer);
1034 if (err != OK) {
1035 ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err);
1036 } else {
1037 onBufferAcquired_l(buffer);
1038 }
1039}
Andy McFaddenf779bb52013-02-19 07:28:30 -08001040
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001041bool GraphicBufferSource::areWeDiscardingAvailableBuffers_l() {
1042 return mEndOfStreamSent // already sent EOS to codec
Wonsik Kim28605732018-01-11 17:11:11 -08001043 || mComponent == nullptr // there is no codec connected
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001044 || (mSuspended && mActionQueue.empty()) // we are suspended and not waiting for
1045 // any further action
1046 || !mExecuting;
1047}
Andreas Hubera61285d2013-07-31 13:50:42 -07001048
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001049void GraphicBufferSource::onBufferAcquired_l(const VideoBuffer &buffer) {
1050 if (mEndOfStreamSent) {
1051 // This should only be possible if a new buffer was queued after
1052 // EOS was signaled, i.e. the app is misbehaving.
1053 ALOGW("onFrameAvailable: EOS is sent, ignoring frame");
Wonsik Kim28605732018-01-11 17:11:11 -08001054 } else if (mComponent == NULL || (mSuspended && mActionQueue.empty())) {
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001055 // FIXME: if we are suspended but have a resume queued we will stop repeating the last
1056 // frame. Is that the desired behavior?
1057 ALOGV("onFrameAvailable: suspended, ignoring frame");
1058 } else {
1059 ++mRepeatLastFrameGeneration; // cancel any pending frame repeat
1060 mAvailableBuffers.push_back(buffer);
1061 if (mExecuting) {
1062 fillCodecBuffer_l();
1063 }
Andy McFaddenf779bb52013-02-19 07:28:30 -08001064 }
1065}
1066
1067// BufferQueue::ConsumerListener callback
1068void GraphicBufferSource::onBuffersReleased() {
1069 Mutex::Autolock lock(mMutex);
1070
Dan Stoza24752642014-04-09 16:10:53 -07001071 uint64_t slotMask;
Lajos Molnar13578392017-09-12 14:20:10 -07001072 uint64_t releaseMask;
1073 if (mConsumer->getReleasedBuffers(&releaseMask) != NO_ERROR) {
Dan Stoza24752642014-04-09 16:10:53 -07001074 slotMask = 0xffffffffffffffffULL;
Lajos Molnar13578392017-09-12 14:20:10 -07001075 ALOGW("onBuffersReleased: unable to get released buffer set");
1076 } else {
1077 slotMask = releaseMask;
1078 ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
Andy McFaddenf779bb52013-02-19 07:28:30 -08001079 }
1080
Lajos Molnar13578392017-09-12 14:20:10 -07001081 AString unpopulated;
Andy McFaddenf779bb52013-02-19 07:28:30 -08001082 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
1083 if ((slotMask & 0x01) != 0) {
Lajos Molnar13578392017-09-12 14:20:10 -07001084 if (!discardBufferInSlot_l(i)) {
1085 if (!unpopulated.empty()) {
1086 unpopulated.append(", ");
1087 }
1088 unpopulated.append(i);
1089 }
Andy McFaddenf779bb52013-02-19 07:28:30 -08001090 }
1091 slotMask >>= 1;
1092 }
Lajos Molnar13578392017-09-12 14:20:10 -07001093 if (!unpopulated.empty()) {
1094 ALOGW("released unpopulated slots: [%s]", unpopulated.c_str());
1095 }
Andy McFaddenf779bb52013-02-19 07:28:30 -08001096}
1097
Lajos Molnar13578392017-09-12 14:20:10 -07001098bool GraphicBufferSource::discardBufferInSlot_l(GraphicBufferSource::slot_id i) {
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001099 ssize_t bsi = mBufferSlots.indexOfKey(i);
1100 if (bsi < 0) {
Lajos Molnar13578392017-09-12 14:20:10 -07001101 return false;
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001102 } else {
1103 discardBufferAtSlotIndex_l(bsi);
1104 mBufferSlots.removeItemsAt(bsi);
Lajos Molnar13578392017-09-12 14:20:10 -07001105 return true;
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001106 }
1107}
1108
1109void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t bsi) {
1110 const std::shared_ptr<CachedBuffer>& buffer = mBufferSlots.valueAt(bsi);
1111 // use -2 if there is no latest buffer, and -1 if it is no longer cached
1112 slot_id latestBufferSlot =
1113 mLatestBuffer.mBuffer == nullptr ? -2 : mLatestBuffer.mBuffer->getSlot();
1114 ALOGV("releasing acquired buffer: [slot=%d, useCount=%ld], latest: [slot=%d]",
1115 mBufferSlots.keyAt(bsi), buffer.use_count(), latestBufferSlot);
1116 mBufferSlots.valueAt(bsi)->onDroppedFromCache();
1117
1118 // If the slot of an acquired buffer is discarded, that buffer will not have to be
1119 // released to the producer, so account it here. However, it is possible that the
1120 // acquired buffer has already been discarded so check if it still is.
1121 if (buffer->isAcquired()) {
1122 --mNumOutstandingAcquires;
1123 }
1124
1125 // clear the buffer reference (not technically needed as caller either replaces or deletes
1126 // it; done here for safety).
1127 mBufferSlots.editValueAt(bsi).reset();
1128 CHECK_DBG(buffer == nullptr);
1129}
1130
1131void GraphicBufferSource::releaseAllAvailableBuffers_l() {
1132 mAvailableBuffers.clear();
1133 while (mNumAvailableUnacquiredBuffers > 0) {
1134 VideoBuffer item;
1135 if (acquireBuffer_l(&item) != OK) {
1136 ALOGW("releaseAllAvailableBuffers: failed to acquire available unacquired buffer");
1137 break;
1138 }
1139 }
1140}
1141
Jesse Hall8dcc81a2014-03-03 15:35:36 -08001142// BufferQueue::ConsumerListener callback
1143void GraphicBufferSource::onSidebandStreamChanged() {
1144 ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
1145}
1146
Robert Shihd095e652017-03-11 01:20:43 +00001147status_t GraphicBufferSource::configure(
Wonsik Kim28605732018-01-11 17:11:11 -08001148 const sp<ComponentWrapper>& component,
Robert Shihd095e652017-03-11 01:20:43 +00001149 int32_t dataSpace,
1150 int32_t bufferCount,
1151 uint32_t frameWidth,
1152 uint32_t frameHeight,
1153 uint32_t consumerUsage) {
Wonsik Kim28605732018-01-11 17:11:11 -08001154 if (component == NULL) {
Robert Shihd095e652017-03-11 01:20:43 +00001155 return BAD_VALUE;
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001156 }
1157
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001158
1159 // Call setMaxAcquiredBufferCount without lock.
1160 // setMaxAcquiredBufferCount could call back to onBuffersReleased
1161 // if the buffer count change results in releasing of existing buffers,
1162 // which would lead to deadlock.
Robert Shihd095e652017-03-11 01:20:43 +00001163 status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001164 if (err != NO_ERROR) {
1165 ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
Robert Shihd095e652017-03-11 01:20:43 +00001166 bufferCount, err);
1167 return err;
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001168 }
1169
1170 {
1171 Mutex::Autolock autoLock(mMutex);
Wonsik Kim28605732018-01-11 17:11:11 -08001172 mComponent = component;
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001173
Robert Shihd095e652017-03-11 01:20:43 +00001174 err = mConsumer->setDefaultBufferSize(frameWidth, frameHeight);
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001175 if (err != NO_ERROR) {
1176 ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
Robert Shihd095e652017-03-11 01:20:43 +00001177 frameWidth, frameHeight, err);
1178 return err;
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001179 }
1180
1181 consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
1182 mConsumer->setConsumerUsageBits(consumerUsage);
1183
Emilian Peev9ff03272018-10-11 19:03:49 +01001184 // Set impl. defined format as default. Depending on the usage flags
1185 // the device-specific implementation will derive the exact format.
1186 err = mConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
1187 if (err != NO_ERROR) {
1188 ALOGE("Failed to configure surface default format ret: %d", err);
1189 return err;
1190 }
1191
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001192 // Sets the default buffer data space
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001193 ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires);
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001194 mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001195 mLastDataspace = (android_dataspace)dataSpace;
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001196
1197 mExecuting = false;
1198 mSuspended = false;
1199 mEndOfStream = false;
1200 mEndOfStreamSent = false;
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -08001201 mSkipFramesBeforeNs = -1LL;
Chong Zhang6c2d0ad2018-05-24 19:36:53 -07001202 mFrameDropper.clear();
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -08001203 mFrameRepeatIntervalUs = -1LL;
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001204 mRepeatLastFrameGeneration = 0;
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001205 mOutstandingFrameRepeatCount = 0;
1206 mLatestBuffer.mBuffer.reset();
1207 mFrameRepeatBlockedOnCodecBuffer = false;
Pawin Vongmasa22dc5082017-04-20 05:12:55 -07001208 mFps = -1.0;
1209 mCaptureFps = -1.0;
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -08001210 mBaseCaptureUs = -1LL;
1211 mBaseFrameUs = -1LL;
1212 mPrevCaptureUs = -1LL;
1213 mPrevFrameUs = -1LL;
Pawin Vongmasa22dc5082017-04-20 05:12:55 -07001214 mFrameCount = 0;
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001215 mInputBufferTimeOffsetUs = 0;
Hangyu Kuang764d9452016-12-13 13:07:45 -08001216 mStopTimeUs = -1;
1217 mActionQueue.clear();
Chong Zhangaddf2cb2016-09-28 17:53:01 -07001218 }
1219
Robert Shihd095e652017-03-11 01:20:43 +00001220 return OK;
Lajos Molnar57fad3c2016-03-08 13:09:35 -08001221}
1222
Robert Shihd095e652017-03-11 01:20:43 +00001223status_t GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
Hangyu Kuang764d9452016-12-13 13:07:45 -08001224 ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs);
Chong Zhang6d332d22016-09-07 12:06:50 -07001225
1226 Mutex::Autolock autoLock(mMutex);
1227
Hangyu Kuang764d9452016-12-13 13:07:45 -08001228 if (mStopTimeUs != -1) {
1229 ALOGE("setSuspend failed as STOP action is pending");
Robert Shihd095e652017-03-11 01:20:43 +00001230 return INVALID_OPERATION;
Chong Zhang6d332d22016-09-07 12:06:50 -07001231 }
1232
Hangyu Kuang764d9452016-12-13 13:07:45 -08001233 // Push the action to the queue.
1234 if (suspendStartTimeUs != -1) {
1235 // suspendStartTimeUs must be smaller or equal to current systemTime.
1236 int64_t currentSystemTimeUs = systemTime() / 1000;
1237 if (suspendStartTimeUs > currentSystemTimeUs) {
1238 ALOGE("setSuspend failed. %lld is larger than current system time %lld us",
1239 (long long)suspendStartTimeUs, (long long)currentSystemTimeUs);
Robert Shihd095e652017-03-11 01:20:43 +00001240 return INVALID_OPERATION;
Hangyu Kuang764d9452016-12-13 13:07:45 -08001241 }
1242 if (mLastActionTimeUs != -1 && suspendStartTimeUs < mLastActionTimeUs) {
1243 ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
1244 (long long)suspendStartTimeUs, (long long)mLastActionTimeUs);
Robert Shihd095e652017-03-11 01:20:43 +00001245 return INVALID_OPERATION;
Hangyu Kuang764d9452016-12-13 13:07:45 -08001246 }
1247 mLastActionTimeUs = suspendStartTimeUs;
1248 ActionItem action;
1249 action.mAction = suspend ? ActionItem::PAUSE : ActionItem::RESUME;
1250 action.mActionTimeUs = suspendStartTimeUs;
1251 ALOGV("Push %s action into actionQueue", suspend ? "PAUSE" : "RESUME");
1252 mActionQueue.push_back(action);
1253 } else {
1254 if (suspend) {
1255 mSuspended = true;
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001256 releaseAllAvailableBuffers_l();
Robert Shihd095e652017-03-11 01:20:43 +00001257 return OK;
Chong Zhang6d332d22016-09-07 12:06:50 -07001258 } else {
Hangyu Kuang764d9452016-12-13 13:07:45 -08001259 mSuspended = false;
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001260 if (mExecuting && !haveAvailableBuffers_l()
1261 && mFrameRepeatBlockedOnCodecBuffer) {
Hangyu Kuang764d9452016-12-13 13:07:45 -08001262 if (repeatLatestBuffer_l()) {
1263 ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001264 mFrameRepeatBlockedOnCodecBuffer = false;
Hangyu Kuang764d9452016-12-13 13:07:45 -08001265 } else {
1266 ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
1267 }
1268 }
Chong Zhang6d332d22016-09-07 12:06:50 -07001269 }
1270 }
Robert Shihd095e652017-03-11 01:20:43 +00001271 return OK;
Chong Zhang6d332d22016-09-07 12:06:50 -07001272}
1273
Robert Shihd095e652017-03-11 01:20:43 +00001274status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
Chong Zhang6d332d22016-09-07 12:06:50 -07001275 ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs);
1276
Andreas Hubera61285d2013-07-31 13:50:42 -07001277 Mutex::Autolock autoLock(mMutex);
1278
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -08001279 if (mExecuting || repeatAfterUs <= 0LL) {
Robert Shihd095e652017-03-11 01:20:43 +00001280 return INVALID_OPERATION;
Andreas Hubera61285d2013-07-31 13:50:42 -07001281 }
1282
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001283 mFrameRepeatIntervalUs = repeatAfterUs;
Robert Shihd095e652017-03-11 01:20:43 +00001284 return OK;
Andreas Hubera61285d2013-07-31 13:50:42 -07001285}
1286
Robert Shihd095e652017-03-11 01:20:43 +00001287status_t GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
Hangyu Kuang61fcfd12016-08-30 13:50:58 -07001288 Mutex::Autolock autoLock(mMutex);
1289
1290 // timeOffsetUs must be negative for adjustment.
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -08001291 if (timeOffsetUs >= 0LL) {
Robert Shihd095e652017-03-11 01:20:43 +00001292 return INVALID_OPERATION;
Hangyu Kuang61fcfd12016-08-30 13:50:58 -07001293 }
1294
1295 mInputBufferTimeOffsetUs = timeOffsetUs;
Robert Shihd095e652017-03-11 01:20:43 +00001296 return OK;
Hangyu Kuang61fcfd12016-08-30 13:50:58 -07001297}
1298
Robert Shihd095e652017-03-11 01:20:43 +00001299status_t GraphicBufferSource::setMaxFps(float maxFps) {
Chong Zhang6d332d22016-09-07 12:06:50 -07001300 ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps);
1301
Ronghua Wu37b2b382015-01-26 15:47:10 -08001302 Mutex::Autolock autoLock(mMutex);
1303
1304 if (mExecuting) {
Robert Shihd095e652017-03-11 01:20:43 +00001305 return INVALID_OPERATION;
Ronghua Wu37b2b382015-01-26 15:47:10 -08001306 }
1307
1308 mFrameDropper = new FrameDropper();
1309 status_t err = mFrameDropper->setMaxFrameRate(maxFps);
1310 if (err != OK) {
1311 mFrameDropper.clear();
Robert Shihd095e652017-03-11 01:20:43 +00001312 return err;
Ronghua Wu37b2b382015-01-26 15:47:10 -08001313 }
1314
Robert Shihd095e652017-03-11 01:20:43 +00001315 return OK;
Ronghua Wu37b2b382015-01-26 15:47:10 -08001316}
1317
Robert Shihd095e652017-03-11 01:20:43 +00001318status_t GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
Chong Zhang6d332d22016-09-07 12:06:50 -07001319 ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs);
1320
Chong Zhang72cecca2013-12-26 01:38:35 -08001321 Mutex::Autolock autoLock(mMutex);
1322
1323 mSkipFramesBeforeNs =
Pawin Vongmasa3a75f042017-11-08 04:44:59 -08001324 (skipFramesBeforeUs > 0 && skipFramesBeforeUs <= INT64_MAX / 1000) ?
Chih-Hung Hsieh3794b242018-12-11 13:55:06 -08001325 (skipFramesBeforeUs * 1000) : -1LL;
Chong Zhang6d332d22016-09-07 12:06:50 -07001326
Robert Shihd095e652017-03-11 01:20:43 +00001327 return OK;
Chong Zhang72cecca2013-12-26 01:38:35 -08001328}
1329
Robert Shihd095e652017-03-11 01:20:43 +00001330status_t GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
Hangyu Kuang764d9452016-12-13 13:07:45 -08001331 ALOGV("setStopTimeUs: %lld us", (long long)stopTimeUs);
1332 Mutex::Autolock autoLock(mMutex);
1333
1334 if (mStopTimeUs != -1) {
1335 // Ignore if stop time has already been set
Robert Shihd095e652017-03-11 01:20:43 +00001336 return OK;
Hangyu Kuang764d9452016-12-13 13:07:45 -08001337 }
1338
1339 // stopTimeUs must be smaller or equal to current systemTime.
1340 int64_t currentSystemTimeUs = systemTime() / 1000;
1341 if (stopTimeUs > currentSystemTimeUs) {
1342 ALOGE("setStopTimeUs failed. %lld is larger than current system time %lld us",
1343 (long long)stopTimeUs, (long long)currentSystemTimeUs);
Robert Shihd095e652017-03-11 01:20:43 +00001344 return INVALID_OPERATION;
Hangyu Kuang764d9452016-12-13 13:07:45 -08001345 }
1346 if (mLastActionTimeUs != -1 && stopTimeUs < mLastActionTimeUs) {
1347 ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
1348 (long long)stopTimeUs, (long long)mLastActionTimeUs);
Robert Shihd095e652017-03-11 01:20:43 +00001349 return INVALID_OPERATION;
Hangyu Kuang764d9452016-12-13 13:07:45 -08001350 }
1351 mLastActionTimeUs = stopTimeUs;
1352 ActionItem action;
1353 action.mAction = ActionItem::STOP;
1354 action.mActionTimeUs = stopTimeUs;
1355 mActionQueue.push_back(action);
1356 mStopTimeUs = stopTimeUs;
Robert Shihd095e652017-03-11 01:20:43 +00001357 return OK;
Hangyu Kuang764d9452016-12-13 13:07:45 -08001358}
1359
Hangyu Kuangf72cefd2017-04-05 11:07:08 -07001360status_t GraphicBufferSource::getStopTimeOffsetUs(int64_t *stopTimeOffsetUs) {
1361 ALOGV("getStopTimeOffsetUs");
1362 Mutex::Autolock autoLock(mMutex);
1363 if (mStopTimeUs == -1) {
1364 ALOGW("Fail to return stopTimeOffsetUs as stop time is not set");
1365 return INVALID_OPERATION;
1366 }
Hangyu Kuangcf3205f2017-06-20 11:25:06 -07001367 *stopTimeOffsetUs =
1368 mLastFrameTimestampUs == -1 ? 0 : mStopTimeUs - mLastFrameTimestampUs;
Hangyu Kuangf72cefd2017-04-05 11:07:08 -07001369 return OK;
1370}
1371
Pawin Vongmasa22dc5082017-04-20 05:12:55 -07001372status_t GraphicBufferSource::setTimeLapseConfig(double fps, double captureFps) {
1373 ALOGV("setTimeLapseConfig: fps=%lg, captureFps=%lg",
1374 fps, captureFps);
Chong Zhang2c9c8cb2014-02-11 13:54:59 -08001375 Mutex::Autolock autoLock(mMutex);
1376
Pawin Vongmasa22dc5082017-04-20 05:12:55 -07001377 if (mExecuting || !(fps > 0) || !(captureFps > 0)) {
Robert Shihd095e652017-03-11 01:20:43 +00001378 return INVALID_OPERATION;
Chong Zhang2c9c8cb2014-02-11 13:54:59 -08001379 }
1380
Pawin Vongmasa22dc5082017-04-20 05:12:55 -07001381 mFps = fps;
1382 mCaptureFps = captureFps;
Pawin Vongmasaee9bde72019-09-11 09:59:08 -07001383 if (captureFps > fps) {
1384 mSnapTimestamps = 1 == base::GetIntProperty(
Pawin Vongmasadef61c92019-09-20 16:53:03 -07001385 "debug.stagefright.snap_timestamps", int64_t(0));
Pawin Vongmasaee9bde72019-09-11 09:59:08 -07001386 } else {
1387 mSnapTimestamps = false;
1388 }
Chong Zhang2c9c8cb2014-02-11 13:54:59 -08001389
Robert Shihd095e652017-03-11 01:20:43 +00001390 return OK;
Chong Zhang2c9c8cb2014-02-11 13:54:59 -08001391}
1392
Robert Shihd095e652017-03-11 01:20:43 +00001393status_t GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
Lajos Molnardd81af72016-03-10 18:19:18 -08001394 Mutex::Autolock autoLock(mMutex);
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001395 mDefaultColorAspectsPacked = aspectsPacked;
Robert Shihd095e652017-03-11 01:20:43 +00001396 ColorAspects colorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
Lajos Molnarb77d03b2016-03-03 14:02:17 -08001397 ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
Robert Shihd095e652017-03-11 01:20:43 +00001398 colorAspects.mRange, asString(colorAspects.mRange),
1399 colorAspects.mPrimaries, asString(colorAspects.mPrimaries),
1400 colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs),
1401 colorAspects.mTransfer, asString(colorAspects.mTransfer));
Chong Zhang6d332d22016-09-07 12:06:50 -07001402
Robert Shihd095e652017-03-11 01:20:43 +00001403 return OK;
Chong Zhang6d332d22016-09-07 12:06:50 -07001404}
1405
Robert Shihd095e652017-03-11 01:20:43 +00001406status_t GraphicBufferSource::signalEndOfInputStream() {
Chong Zhang6d332d22016-09-07 12:06:50 -07001407 Mutex::Autolock autoLock(mMutex);
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001408 ALOGV("signalEndOfInputStream: executing=%d available=%zu+%d eos=%d",
1409 mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream);
Chong Zhang6d332d22016-09-07 12:06:50 -07001410
1411 if (mEndOfStream) {
1412 ALOGE("EOS was already signaled");
Robert Shihd095e652017-03-11 01:20:43 +00001413 return INVALID_OPERATION;
Chong Zhang6d332d22016-09-07 12:06:50 -07001414 }
1415
1416 // Set the end-of-stream flag. If no frames are pending from the
1417 // BufferQueue, and a codec buffer is available, and we're executing,
Hangyu Kuang764d9452016-12-13 13:07:45 -08001418 // and there is no stop timestamp, we initiate the EOS from here.
Wonsik Kim28605732018-01-11 17:11:11 -08001419 // Otherwise, we'll let codecBufferEmptied() (or start) do it.
Chong Zhang6d332d22016-09-07 12:06:50 -07001420 //
1421 // Note: if there are no pending frames and all codec buffers are
1422 // available, we *must* submit the EOS from here or we'll just
1423 // stall since no future events are expected.
1424 mEndOfStream = true;
1425
hkuang90874e32020-03-17 09:46:49 -07001426 if (mStopTimeUs == -1 && mExecuting && !haveAvailableBuffers_l()) {
Chong Zhang6d332d22016-09-07 12:06:50 -07001427 submitEndOfInputStream_l();
1428 }
1429
Robert Shihd095e652017-03-11 01:20:43 +00001430 return OK;
Lajos Molnardd81af72016-03-10 18:19:18 -08001431}
1432
Andreas Hubera61285d2013-07-31 13:50:42 -07001433void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
1434 switch (msg->what()) {
1435 case kWhatRepeatLastFrame:
1436 {
1437 Mutex::Autolock autoLock(mMutex);
1438
1439 int32_t generation;
1440 CHECK(msg->findInt32("generation", &generation));
1441
1442 if (generation != mRepeatLastFrameGeneration) {
1443 // stale
1444 break;
1445 }
1446
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001447 if (!mExecuting || haveAvailableBuffers_l()) {
Andreas Hubera61285d2013-07-31 13:50:42 -07001448 break;
1449 }
1450
Ronghua Wu37b2b382015-01-26 15:47:10 -08001451 bool success = repeatLatestBuffer_l();
Andreas Hubera61285d2013-07-31 13:50:42 -07001452 if (success) {
Ronghua Wu37b2b382015-01-26 15:47:10 -08001453 ALOGV("repeatLatestBuffer_l SUCCESS");
Andreas Hubera61285d2013-07-31 13:50:42 -07001454 } else {
Ronghua Wu37b2b382015-01-26 15:47:10 -08001455 ALOGV("repeatLatestBuffer_l FAILURE");
Lajos Molnar43fb79a2017-04-06 14:27:17 -07001456 mFrameRepeatBlockedOnCodecBuffer = true;
Andreas Hubera61285d2013-07-31 13:50:42 -07001457 }
1458 break;
1459 }
1460
1461 default:
1462 TRESPASS();
1463 }
1464}
1465
Andy McFaddenf779bb52013-02-19 07:28:30 -08001466} // namespace android