1 /*
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
17 #include <inttypes.h>
18
19 #define LOG_TAG "GraphicBufferSource"
20 //#define LOG_NDEBUG 0
21 #include <utils/Log.h>
22
23 #define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h
24
25 #include <media/stagefright/bqhelper/GraphicBufferSource.h>
26 #include <media/stagefright/bqhelper/FrameDropper.h>
27 #include <media/stagefright/foundation/ADebug.h>
28 #include <media/stagefright/foundation/AMessage.h>
29 #include <media/stagefright/foundation/ColorUtils.h>
30 #include <media/stagefright/foundation/FileDescriptor.h>
31
32 #include <media/hardware/MetadataBufferType.h>
33 #include <ui/GraphicBuffer.h>
34 #include <gui/BufferItem.h>
35 #include <gui/BufferQueue.h>
36 #include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
37 #include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
38 #include <gui/IGraphicBufferProducer.h>
39 #include <gui/IGraphicBufferConsumer.h>
40 #include <media/hardware/HardwareAPI.h>
41
42 #include <inttypes.h>
43
44 #include <functional>
45 #include <memory>
46 #include <cmath>
47
48 namespace android {
49
50 namespace {
51 // kTimestampFluctuation is an upper bound of timestamp fluctuation from the
52 // source that GraphicBufferSource allows. The unit of kTimestampFluctuation is
53 // frames. More specifically, GraphicBufferSource will drop a frame if
54 //
55 // expectedNewFrametimestamp - actualNewFrameTimestamp <
56 // (0.5 - kTimestampFluctuation) * expectedtimePeriodBetweenFrames
57 //
58 // where
59 // - expectedNewFrameTimestamp is the calculated ideal timestamp of the new
60 // incoming frame
61 // - actualNewFrameTimestamp is the timestamp received from the source
62 // - expectedTimePeriodBetweenFrames is the ideal difference of the timestamps
63 // of two adjacent frames
64 //
65 // See GraphicBufferSource::calculateCodecTimestamp_l() for more detail about
66 // how kTimestampFluctuation is used.
67 //
68 // kTimestampFluctuation should be non-negative. A higher value causes a smaller
69 // chance of dropping frames, but at the same time a higher bound on the
70 // difference between the source timestamp and the interpreted (snapped)
71 // timestamp.
72 //
73 // The value of 0.05 means that GraphicBufferSource expects the input timestamps
74 // to fluctuate no more than 5% from the regular time period.
75 //
76 // TODO: Justify the choice of this value, or make it configurable.
77 constexpr double kTimestampFluctuation = 0.05;
78 }
79
80 /**
81 * A copiable object managing a buffer in the buffer cache managed by the producer. This object
82 * holds a reference to the buffer, and maintains which buffer slot it belongs to (if any), and
83 * whether it is still in a buffer slot. It also maintains whether there are any outstanging acquire
84 * references to it (by buffers acquired from the slot) mainly so that we can keep a debug
85 * count of how many buffers we need to still release back to the producer.
86 */
87 struct GraphicBufferSource::CachedBuffer {
88 /**
89 * Token that is used to track acquire counts (as opposed to all references to this object).
90 */
91 struct Acquirable { };
92
93 /**
94 * Create using a buffer cached in a slot.
95 */
CachedBufferandroid::GraphicBufferSource::CachedBuffer96 CachedBuffer(slot_id slot, const sp<GraphicBuffer> &graphicBuffer)
97 : mIsCached(true),
98 mSlot(slot),
99 mGraphicBuffer(graphicBuffer),
100 mAcquirable(std::make_shared<Acquirable>()) {
101 }
102
103 /**
104 * Returns the cache slot that this buffer is cached in, or -1 if it is no longer cached.
105 *
106 * This assumes that -1 slot id is invalid; though, it is just a benign collision used for
107 * debugging. This object explicitly manages whether it is still cached.
108 */
getSlotandroid::GraphicBufferSource::CachedBuffer109 slot_id getSlot() const {
110 return mIsCached ? mSlot : -1;
111 }
112
113 /**
114 * Returns the cached buffer.
115 */
getGraphicBufferandroid::GraphicBufferSource::CachedBuffer116 sp<GraphicBuffer> getGraphicBuffer() const {
117 return mGraphicBuffer;
118 }
119
120 /**
121 * Checks whether this buffer is still in the buffer cache.
122 */
isCachedandroid::GraphicBufferSource::CachedBuffer123 bool isCached() const {
124 return mIsCached;
125 }
126
127 /**
128 * Checks whether this buffer has an acquired reference.
129 */
isAcquiredandroid::GraphicBufferSource::CachedBuffer130 bool isAcquired() const {
131 return mAcquirable.use_count() > 1;
132 }
133
134 /**
135 * Gets and returns a shared acquired reference.
136 */
getAcquirableandroid::GraphicBufferSource::CachedBuffer137 std::shared_ptr<Acquirable> getAcquirable() {
138 return mAcquirable;
139 }
140
141 private:
142 friend void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t);
143
144 /**
145 * This method to be called when the buffer is no longer in the buffer cache.
146 * Called from discardBufferAtSlotIndex_l.
147 */
onDroppedFromCacheandroid::GraphicBufferSource::CachedBuffer148 void onDroppedFromCache() {
149 CHECK_DBG(mIsCached);
150 mIsCached = false;
151 }
152
153 bool mIsCached;
154 slot_id mSlot;
155 sp<GraphicBuffer> mGraphicBuffer;
156 std::shared_ptr<Acquirable> mAcquirable;
157 };
158
159 /**
160 * A copiable object managing a buffer acquired from the producer. This must always be a cached
161 * buffer. This objects also manages its acquire fence and any release fences that may be returned
162 * by the encoder for this buffer (this buffer may be queued to the encoder multiple times).
163 * If no release fences are added by the encoder, the acquire fence is returned as the release
164 * fence for this - as it is assumed that noone waited for the acquire fence. Otherwise, it is
165 * assumed that the encoder has waited for the acquire fence (or returned it as the release
166 * fence).
167 */
168 struct GraphicBufferSource::AcquiredBuffer {
AcquiredBufferandroid::GraphicBufferSource::AcquiredBuffer169 AcquiredBuffer(
170 const std::shared_ptr<CachedBuffer> &buffer,
171 std::function<void(AcquiredBuffer *)> onReleased,
172 const sp<Fence> &acquireFence)
173 : mBuffer(buffer),
174 mAcquirable(buffer->getAcquirable()),
175 mAcquireFence(acquireFence),
176 mGotReleaseFences(false),
177 mOnReleased(onReleased) {
178 }
179
180 /**
181 * Adds a release fence returned by the encoder to this object. If this is called with an
182 * valid file descriptor, it is added to the list of release fences. These are returned to the
183 * producer on release() as a merged fence. Regardless of the validity of the file descriptor,
184 * we take note that a release fence was attempted to be added and the acquire fence can now be
185 * assumed as acquired.
186 */
addReleaseFenceFdandroid::GraphicBufferSource::AcquiredBuffer187 void addReleaseFenceFd(int fenceFd) {
188 // save all release fences - these will be propagated to the producer if this buffer is
189 // ever released to it
190 if (fenceFd >= 0) {
191 mReleaseFenceFds.push_back(fenceFd);
192 }
193 mGotReleaseFences = true;
194 }
195
196 /**
197 * Returns the acquire fence file descriptor associated with this object.
198 */
getAcquireFenceFdandroid::GraphicBufferSource::AcquiredBuffer199 int getAcquireFenceFd() {
200 if (mAcquireFence == nullptr || !mAcquireFence->isValid()) {
201 return -1;
202 }
203 return mAcquireFence->dup();
204 }
205
206 /**
207 * Returns whether the buffer is still in the buffer cache.
208 */
isCachedandroid::GraphicBufferSource::AcquiredBuffer209 bool isCached() const {
210 return mBuffer->isCached();
211 }
212
213 /**
214 * Returns the acquired buffer.
215 */
getGraphicBufferandroid::GraphicBufferSource::AcquiredBuffer216 sp<GraphicBuffer> getGraphicBuffer() const {
217 return mBuffer->getGraphicBuffer();
218 }
219
220 /**
221 * Returns the slot that this buffer is cached at, or -1 otherwise.
222 *
223 * This assumes that -1 slot id is invalid; though, it is just a benign collision used for
224 * debugging. This object explicitly manages whether it is still cached.
225 */
getSlotandroid::GraphicBufferSource::AcquiredBuffer226 slot_id getSlot() const {
227 return mBuffer->getSlot();
228 }
229
230 /**
231 * Creates and returns a release fence object from the acquire fence and/or any release fences
232 * added. If no release fences were added (even if invalid), returns the acquire fence.
233 * Otherwise, it returns a merged fence from all the valid release fences added.
234 */
getReleaseFenceandroid::GraphicBufferSource::AcquiredBuffer235 sp<Fence> getReleaseFence() {
236 // If did not receive release fences, we assume this buffer was not consumed (it was
237 // discarded or dropped). In this case release the acquire fence as the release fence.
238 // We do this here to avoid a dup, close and recreation of the Fence object.
239 if (!mGotReleaseFences) {
240 return mAcquireFence;
241 }
242 sp<Fence> ret = getReleaseFence(0, mReleaseFenceFds.size());
243 // clear fds as fence took ownership of them
244 mReleaseFenceFds.clear();
245 return ret;
246 }
247
248 // this video buffer is no longer referenced by the codec (or kept for later encoding)
249 // it is now safe to release to the producer
~AcquiredBufferandroid::GraphicBufferSource::AcquiredBuffer250 ~AcquiredBuffer() {
251 //mAcquirable.clear();
252 mOnReleased(this);
253 // mOnRelease method should call getReleaseFence() that releases all fds but just in case
254 ALOGW_IF(!mReleaseFenceFds.empty(), "release fences were not obtained, closing fds");
255 for (int fildes : mReleaseFenceFds) {
256 ::close(fildes);
257 TRESPASS_DBG();
258 }
259 }
260
261 private:
262 std::shared_ptr<GraphicBufferSource::CachedBuffer> mBuffer;
263 std::shared_ptr<GraphicBufferSource::CachedBuffer::Acquirable> mAcquirable;
264 sp<Fence> mAcquireFence;
265 Vector<int> mReleaseFenceFds;
266 bool mGotReleaseFences;
267 std::function<void(AcquiredBuffer *)> mOnReleased;
268
269 /**
270 * Creates and returns a release fence from 0 or more release fence file descriptors in from
271 * the specified range in the array.
272 *
273 * @param start start index
274 * @param num number of release fds to merge
275 */
getReleaseFenceandroid::GraphicBufferSource::AcquiredBuffer276 sp<Fence> getReleaseFence(size_t start, size_t num) const {
277 if (num == 0) {
278 return Fence::NO_FENCE;
279 } else if (num == 1) {
280 return new Fence(mReleaseFenceFds[start]);
281 } else {
282 return Fence::merge("GBS::AB",
283 getReleaseFence(start, num >> 1),
284 getReleaseFence(start + (num >> 1), num - (num >> 1)));
285 }
286 }
287 };
288
289 struct GraphicBufferSource::ConsumerProxy : public BufferQueue::ConsumerListener {
ConsumerProxyandroid::GraphicBufferSource::ConsumerProxy290 ConsumerProxy(const wp<GraphicBufferSource> &gbs) : mGbs(gbs) {}
291
292 ~ConsumerProxy() = default;
293
onFrameAvailableandroid::GraphicBufferSource::ConsumerProxy294 void onFrameAvailable(const BufferItem& item) override {
295 sp<GraphicBufferSource> gbs = mGbs.promote();
296 if (gbs != nullptr) {
297 gbs->onFrameAvailable(item);
298 }
299 }
300
onBuffersReleasedandroid::GraphicBufferSource::ConsumerProxy301 void onBuffersReleased() override {
302 sp<GraphicBufferSource> gbs = mGbs.promote();
303 if (gbs != nullptr) {
304 gbs->onBuffersReleased();
305 }
306 }
307
onSidebandStreamChangedandroid::GraphicBufferSource::ConsumerProxy308 void onSidebandStreamChanged() override {
309 sp<GraphicBufferSource> gbs = mGbs.promote();
310 if (gbs != nullptr) {
311 gbs->onSidebandStreamChanged();
312 }
313 }
314
315 private:
316 // Note that GraphicBufferSource is holding an sp to us, we can't hold
317 // an sp back to GraphicBufferSource as the circular dependency will
318 // make both immortal.
319 wp<GraphicBufferSource> mGbs;
320 };
321
GraphicBufferSource()322 GraphicBufferSource::GraphicBufferSource() :
323 mInitCheck(UNKNOWN_ERROR),
324 mNumAvailableUnacquiredBuffers(0),
325 mNumOutstandingAcquires(0),
326 mEndOfStream(false),
327 mEndOfStreamSent(false),
328 mLastDataspace(HAL_DATASPACE_UNKNOWN),
329 mExecuting(false),
330 mSuspended(false),
331 mLastFrameTimestampUs(-1),
332 mStopTimeUs(-1),
333 mLastActionTimeUs(-1LL),
334 mSkipFramesBeforeNs(-1LL),
335 mFrameRepeatIntervalUs(-1LL),
336 mRepeatLastFrameGeneration(0),
337 mOutstandingFrameRepeatCount(0),
338 mFrameRepeatBlockedOnCodecBuffer(false),
339 mFps(-1.0),
340 mCaptureFps(-1.0),
341 mBaseCaptureUs(-1LL),
342 mBaseFrameUs(-1LL),
343 mFrameCount(0),
344 mPrevCaptureUs(-1LL),
345 mPrevFrameUs(-1LL),
346 mInputBufferTimeOffsetUs(0LL) {
347 ALOGV("GraphicBufferSource");
348
349 String8 name("GraphicBufferSource");
350
351 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
352 mConsumer->setConsumerName(name);
353
354 // create the consumer listener interface, and hold sp so that this
355 // interface lives as long as the GraphicBufferSource.
356 mConsumerProxy = new ConsumerProxy(this);
357
358 sp<IConsumerListener> proxy =
359 new BufferQueue::ProxyConsumerListener(mConsumerProxy);
360
361 mInitCheck = mConsumer->consumerConnect(proxy, false);
362 if (mInitCheck != NO_ERROR) {
363 ALOGE("Error connecting to BufferQueue: %s (%d)",
364 strerror(-mInitCheck), mInitCheck);
365 return;
366 }
367
368 memset(&mDefaultColorAspectsPacked, 0, sizeof(mDefaultColorAspectsPacked));
369
370 CHECK(mInitCheck == NO_ERROR);
371 }
372
~GraphicBufferSource()373 GraphicBufferSource::~GraphicBufferSource() {
374 ALOGV("~GraphicBufferSource");
375 {
376 // all acquired buffers must be freed with the mutex locked otherwise our debug assertion
377 // may trigger
378 Mutex::Autolock autoLock(mMutex);
379 mAvailableBuffers.clear();
380 mSubmittedCodecBuffers.clear();
381 mLatestBuffer.mBuffer.reset();
382 }
383
384 if (mNumOutstandingAcquires != 0) {
385 ALOGW("potential buffer leak: acquired=%d", mNumOutstandingAcquires);
386 TRESPASS_DBG();
387 }
388 if (mConsumer != NULL) {
389 status_t err = mConsumer->consumerDisconnect();
390 if (err != NO_ERROR) {
391 ALOGW("consumerDisconnect failed: %d", err);
392 }
393 }
394 }
395
getIGraphicBufferProducer() const396 sp<IGraphicBufferProducer> GraphicBufferSource::getIGraphicBufferProducer() const {
397 return mProducer;
398 }
399
400 sp<::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>
getHGraphicBufferProducer_V1_0() const401 GraphicBufferSource::getHGraphicBufferProducer_V1_0() const {
402 using TWGraphicBufferProducer = ::android::TWGraphicBufferProducer<
403 ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>;
404
405 return new TWGraphicBufferProducer(getIGraphicBufferProducer());
406 }
407
408 sp<::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer>
getHGraphicBufferProducer() const409 GraphicBufferSource::getHGraphicBufferProducer() const {
410 return new ::android::hardware::graphics::bufferqueue::V2_0::utils::
411 B2HGraphicBufferProducer(getIGraphicBufferProducer());
412 }
413
start()414 Status GraphicBufferSource::start() {
415 Mutex::Autolock autoLock(mMutex);
416 ALOGV("--> start; available=%zu, submittable=%zd",
417 mAvailableBuffers.size(), mFreeCodecBuffers.size());
418 CHECK(!mExecuting);
419 mExecuting = true;
420 mLastDataspace = HAL_DATASPACE_UNKNOWN;
421 ALOGV("clearing last dataSpace");
422
423 // Start by loading up as many buffers as possible. We want to do this,
424 // rather than just submit the first buffer, to avoid a degenerate case:
425 // if all BQ buffers arrive before we start executing, and we only submit
426 // one here, the other BQ buffers will just sit until we get notified
427 // that the codec buffer has been released. We'd then acquire and
428 // submit a single additional buffer, repeatedly, never using more than
429 // one codec buffer simultaneously. (We could instead try to submit
430 // all BQ buffers whenever any codec buffer is freed, but if we get the
431 // initial conditions right that will never be useful.)
432 while (haveAvailableBuffers_l()) {
433 if (!fillCodecBuffer_l()) {
434 ALOGV("stop load with available=%zu+%d",
435 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
436 break;
437 }
438 }
439
440 ALOGV("done loading initial frames, available=%zu+%d",
441 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
442
443 // If EOS has already been signaled, and there are no more frames to
444 // submit, try to send EOS now as well.
445 if (mStopTimeUs == -1 && mEndOfStream && !haveAvailableBuffers_l()) {
446 submitEndOfInputStream_l();
447 }
448
449 if (mFrameRepeatIntervalUs > 0LL && mLooper == NULL) {
450 mReflector = new AHandlerReflector<GraphicBufferSource>(this);
451
452 mLooper = new ALooper;
453 mLooper->registerHandler(mReflector);
454 mLooper->start();
455
456 if (mLatestBuffer.mBuffer != nullptr) {
457 queueFrameRepeat_l();
458 }
459 }
460
461 return Status::ok();
462 }
463
stop()464 Status GraphicBufferSource::stop() {
465 ALOGV("stop");
466
467 Mutex::Autolock autoLock(mMutex);
468
469 if (mExecuting) {
470 // We are only interested in the transition from executing->idle,
471 // not loaded->idle.
472 mExecuting = false;
473 }
474 return Status::ok();
475 }
476
release()477 Status GraphicBufferSource::release(){
478 sp<ALooper> looper;
479 {
480 Mutex::Autolock autoLock(mMutex);
481 looper = mLooper;
482 if (mLooper != NULL) {
483 mLooper->unregisterHandler(mReflector->id());
484 mReflector.clear();
485
486 mLooper.clear();
487 }
488
489 ALOGV("--> release; available=%zu+%d eos=%d eosSent=%d acquired=%d",
490 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers,
491 mEndOfStream, mEndOfStreamSent, mNumOutstandingAcquires);
492
493 // Codec is no longer executing. Releasing all buffers to bq.
494 mFreeCodecBuffers.clear();
495 mSubmittedCodecBuffers.clear();
496 mLatestBuffer.mBuffer.reset();
497 mComponent.clear();
498 mExecuting = false;
499 }
500 if (looper != NULL) {
501 looper->stop();
502 }
503 return Status::ok();
504 }
505
onInputBufferAdded(codec_buffer_id bufferId)506 Status GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) {
507 Mutex::Autolock autoLock(mMutex);
508
509 if (mExecuting) {
510 // This should never happen -- buffers can only be allocated when
511 // transitioning from "loaded" to "idle".
512 ALOGE("addCodecBuffer: buffer added while executing");
513 return Status::fromServiceSpecificError(INVALID_OPERATION);
514 }
515
516 ALOGV("addCodecBuffer: bufferId=%u", bufferId);
517
518 mFreeCodecBuffers.push_back(bufferId);
519 return Status::ok();
520 }
521
onInputBufferEmptied(codec_buffer_id bufferId,int fenceFd)522 Status GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) {
523 Mutex::Autolock autoLock(mMutex);
524 FileDescriptor::Autoclose fence(fenceFd);
525
526 ssize_t cbi = mSubmittedCodecBuffers.indexOfKey(bufferId);
527 if (cbi < 0) {
528 // This should never happen.
529 ALOGE("onInputBufferEmptied: buffer not recognized (bufferId=%u)", bufferId);
530 return Status::fromServiceSpecificError(BAD_VALUE);
531 }
532
533 std::shared_ptr<AcquiredBuffer> buffer = mSubmittedCodecBuffers.valueAt(cbi);
534
535 // Move buffer to available buffers
536 mSubmittedCodecBuffers.removeItemsAt(cbi);
537 mFreeCodecBuffers.push_back(bufferId);
538
539 // header->nFilledLen may not be the original value, so we can't compare
540 // that to zero to see of this was the EOS buffer. Instead we just
541 // see if there is a null AcquiredBuffer, which should only ever happen for EOS.
542 if (buffer == nullptr) {
543 if (!(mEndOfStream && mEndOfStreamSent)) {
544 // This can happen when broken code sends us the same buffer twice in a row.
545 ALOGE("onInputBufferEmptied: non-EOS null buffer (bufferId=%u)", bufferId);
546 } else {
547 ALOGV("onInputBufferEmptied: EOS null buffer (bufferId=%u@%zd)", bufferId, cbi);
548 }
549 // No GraphicBuffer to deal with, no additional input or output is expected, so just return.
550 return Status::fromServiceSpecificError(BAD_VALUE);
551 }
552
553 if (!mExecuting) {
554 // this is fine since this could happen when going from Idle to Loaded
555 ALOGV("onInputBufferEmptied: no longer executing (bufferId=%u@%zd)", bufferId, cbi);
556 return Status::fromServiceSpecificError(OK);
557 }
558
559 ALOGV("onInputBufferEmptied: bufferId=%d@%zd [slot=%d, useCount=%ld, handle=%p] acquired=%d",
560 bufferId, cbi, buffer->getSlot(), buffer.use_count(), buffer->getGraphicBuffer()->handle,
561 mNumOutstandingAcquires);
562
563 buffer->addReleaseFenceFd(fence.release());
564 // release codec reference for video buffer just in case remove does not it
565 buffer.reset();
566
567 if (haveAvailableBuffers_l()) {
568 // Fill this codec buffer.
569 CHECK(!mEndOfStreamSent);
570 ALOGV("onInputBufferEmptied: buffer freed, feeding codec (available=%zu+%d, eos=%d)",
571 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream);
572 fillCodecBuffer_l();
573 } else if (mEndOfStream && mStopTimeUs == -1) {
574 // No frames available, but EOS is pending and no stop time, so use this buffer to
575 // send that.
576 ALOGV("onInputBufferEmptied: buffer freed, submitting EOS");
577 submitEndOfInputStream_l();
578 } else if (mFrameRepeatBlockedOnCodecBuffer) {
579 bool success = repeatLatestBuffer_l();
580 ALOGV("onInputBufferEmptied: completing deferred repeatLatestBuffer_l %s",
581 success ? "SUCCESS" : "FAILURE");
582 mFrameRepeatBlockedOnCodecBuffer = false;
583 }
584
585 // releaseReleasableBuffers_l();
586 return Status::ok();
587 }
588
onDataspaceChanged_l(android_dataspace dataspace,android_pixel_format pixelFormat)589 void GraphicBufferSource::onDataspaceChanged_l(
590 android_dataspace dataspace, android_pixel_format pixelFormat) {
591 ALOGD("got buffer with new dataSpace #%x", dataspace);
592 mLastDataspace = dataspace;
593
594 if (ColorUtils::convertDataSpaceToV0(dataspace)) {
595 mComponent->dispatchDataSpaceChanged(
596 mLastDataspace, mDefaultColorAspectsPacked, pixelFormat);
597 }
598 }
599
fillCodecBuffer_l()600 bool GraphicBufferSource::fillCodecBuffer_l() {
601 CHECK(mExecuting && haveAvailableBuffers_l());
602
603 if (mFreeCodecBuffers.empty()) {
604 // No buffers available, bail.
605 ALOGV("fillCodecBuffer_l: no codec buffers, available=%zu+%d",
606 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
607 return false;
608 }
609
610 VideoBuffer item;
611 if (mAvailableBuffers.empty()) {
612 ALOGV("fillCodecBuffer_l: acquiring available buffer, available=%zu+%d",
613 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
614 if (acquireBuffer_l(&item) != OK) {
615 ALOGE("fillCodecBuffer_l: failed to acquire available buffer");
616 return false;
617 }
618 } else {
619 ALOGV("fillCodecBuffer_l: getting available buffer, available=%zu+%d",
620 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
621 item = *mAvailableBuffers.begin();
622 mAvailableBuffers.erase(mAvailableBuffers.begin());
623 }
624
625 int64_t itemTimeUs = item.mTimestampNs / 1000;
626
627 // Process ActionItem in the Queue if there is any. If a buffer's timestamp
628 // is smaller than the first action's timestamp, no action need to be performed.
629 // If buffer's timestamp is larger or equal than the last action's timestamp,
630 // only the last action needs to be performed as all the acitions before the
631 // the action are overridden by the last action. For the other cases, traverse
632 // the Queue to find the newest action that with timestamp smaller or equal to
633 // the buffer's timestamp. For example, an action queue like
634 // [pause 1us], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon
635 // receiving a buffer with timestamp 3.5us, only the action [pause, 3us] needs
636 // to be handled and [pause, 1us], [resume 2us] will be discarded.
637 bool done = false;
638 bool seeStopAction = false;
639 if (!mActionQueue.empty()) {
640 // First scan to check if bufferTimestamp is smaller than first action's timestamp.
641 ActionItem nextAction = *(mActionQueue.begin());
642 if (itemTimeUs < nextAction.mActionTimeUs) {
643 ALOGV("No action. buffer timestamp %lld us < action timestamp: %lld us",
644 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
645 // All the actions are ahead. No action need to perform now.
646 // Release the buffer if is in suspended state, or process the buffer
647 // if not in suspended state.
648 done = true;
649 }
650
651 if (!done) {
652 // Find the newest action that with timestamp smaller than itemTimeUs. Then
653 // remove all the actions before and include the newest action.
654 List<ActionItem>::iterator it = mActionQueue.begin();
655 while (it != mActionQueue.end() && it->mActionTimeUs <= itemTimeUs
656 && nextAction.mAction != ActionItem::STOP) {
657 nextAction = *it;
658 ++it;
659 }
660 mActionQueue.erase(mActionQueue.begin(), it);
661
662 CHECK(itemTimeUs >= nextAction.mActionTimeUs);
663 switch (nextAction.mAction) {
664 case ActionItem::PAUSE:
665 {
666 mSuspended = true;
667 ALOGV("RUNNING/PAUSE -> PAUSE at buffer %lld us PAUSE Time: %lld us",
668 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
669 break;
670 }
671 case ActionItem::RESUME:
672 {
673 mSuspended = false;
674 ALOGV("PAUSE/RUNNING -> RUNNING at buffer %lld us RESUME Time: %lld us",
675 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
676 break;
677 }
678 case ActionItem::STOP:
679 {
680 ALOGV("RUNNING/PAUSE -> STOP at buffer %lld us STOP Time: %lld us",
681 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
682 // Clear the whole ActionQueue as recording is done
683 mActionQueue.clear();
684 seeStopAction = true;
685 break;
686 }
687 default:
688 TRESPASS_DBG("Unknown action type");
689 // return true here because we did consume an available buffer, so the
690 // loop in start will eventually terminate even if we hit this.
691 return false;
692 }
693 }
694 }
695
696 if (seeStopAction) {
697 // Clear all the buffers before setting mEndOfStream and signal EndOfInputStream.
698 releaseAllAvailableBuffers_l();
699 mEndOfStream = true;
700 submitEndOfInputStream_l();
701 return true;
702 }
703
704 if (mSuspended) {
705 return true;
706 }
707
708 int err = UNKNOWN_ERROR;
709
710 // only submit sample if start time is unspecified, or sample
711 // is queued after the specified start time
712 if (mSkipFramesBeforeNs < 0LL || item.mTimestampNs >= mSkipFramesBeforeNs) {
713 // if start time is set, offset time stamp by start time
714 if (mSkipFramesBeforeNs > 0) {
715 item.mTimestampNs -= mSkipFramesBeforeNs;
716 }
717
718 int64_t timeUs = item.mTimestampNs / 1000;
719 if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) {
720 ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs));
721 // set err to OK so that the skipped frame can still be saved as the lastest frame
722 err = OK;
723 } else {
724 err = submitBuffer_l(item); // this takes shared ownership of the acquired buffer on succeess
725 }
726 }
727
728 if (err != OK) {
729 ALOGV("submitBuffer_l failed, will release bq slot %d", item.mBuffer->getSlot());
730 return true;
731 } else {
732 // Don't set the last buffer id if we're not repeating,
733 // we'll be holding on to the last buffer for nothing.
734 if (mFrameRepeatIntervalUs > 0LL) {
735 setLatestBuffer_l(item);
736 }
737 ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d",
738 item.mBuffer->getSlot(), item.mBuffer.use_count(), mNumOutstandingAcquires);
739 mLastFrameTimestampUs = itemTimeUs;
740 }
741
742 return true;
743 }
744
repeatLatestBuffer_l()745 bool GraphicBufferSource::repeatLatestBuffer_l() {
746 CHECK(mExecuting && !haveAvailableBuffers_l());
747
748 if (mLatestBuffer.mBuffer == nullptr || mSuspended) {
749 return false;
750 }
751
752 if (mFreeCodecBuffers.empty()) {
753 // No buffers available, bail.
754 ALOGV("repeatLatestBuffer_l: no codec buffers.");
755 return false;
756 }
757
758 if (!mLatestBuffer.mBuffer->isCached()) {
759 ALOGV("repeatLatestBuffer_l: slot was discarded, but repeating our own reference");
760 }
761
762 // it is ok to update the timestamp of latest buffer as it is only used for submission
763 status_t err = submitBuffer_l(mLatestBuffer);
764 if (err != OK) {
765 return false;
766 }
767
768 /* repeat last frame up to kRepeatLastFrameCount times.
769 * in case of static scene, a single repeat might not get rid of encoder
770 * ghosting completely, refresh a couple more times to get better quality
771 */
772 if (--mOutstandingFrameRepeatCount > 0) {
773 // set up timestamp for repeat frame
774 mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000;
775 queueFrameRepeat_l();
776 }
777
778 return true;
779 }
780
setLatestBuffer_l(const VideoBuffer & item)781 void GraphicBufferSource::setLatestBuffer_l(const VideoBuffer &item) {
782 mLatestBuffer = item;
783
784 ALOGV("setLatestBuffer_l: [slot=%d, useCount=%ld]",
785 mLatestBuffer.mBuffer->getSlot(), mLatestBuffer.mBuffer.use_count());
786
787 mOutstandingFrameRepeatCount = kRepeatLastFrameCount;
788 // set up timestamp for repeat frame
789 mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000;
790 queueFrameRepeat_l();
791 }
792
queueFrameRepeat_l()793 void GraphicBufferSource::queueFrameRepeat_l() {
794 mFrameRepeatBlockedOnCodecBuffer = false;
795
796 if (mReflector != NULL) {
797 sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
798 msg->setInt32("generation", ++mRepeatLastFrameGeneration);
799 msg->post(mFrameRepeatIntervalUs);
800 }
801 }
802
calculateCodecTimestamp_l(nsecs_t bufferTimeNs,int64_t * codecTimeUs)803 bool GraphicBufferSource::calculateCodecTimestamp_l(
804 nsecs_t bufferTimeNs, int64_t *codecTimeUs) {
805 int64_t timeUs = bufferTimeNs / 1000;
806 timeUs += mInputBufferTimeOffsetUs;
807
808 if (mCaptureFps > 0.
809 && (mFps > 2 * mCaptureFps
810 || mCaptureFps > 2 * mFps)) {
811 // Time lapse or slow motion mode
812 if (mPrevCaptureUs < 0LL) {
813 // first capture
814 mPrevCaptureUs = mBaseCaptureUs = timeUs;
815 // adjust the first sample timestamp.
816 mPrevFrameUs = mBaseFrameUs =
817 std::llround((timeUs * mCaptureFps) / mFps);
818 mFrameCount = 0;
819 } else {
820 // snap to nearest capture point
821 double nFrames = (timeUs - mPrevCaptureUs) * mCaptureFps / 1000000;
822 if (nFrames < 0.5 - kTimestampFluctuation) {
823 // skip this frame as it's too close to previous capture
824 ALOGD("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
825 return false;
826 }
827 if (nFrames <= 1.0) {
828 nFrames = 1.0;
829 }
830 mFrameCount += std::llround(nFrames);
831 mPrevCaptureUs = mBaseCaptureUs + std::llround(
832 mFrameCount * 1000000 / mCaptureFps);
833 mPrevFrameUs = mBaseFrameUs + std::llround(
834 mFrameCount * 1000000 / mFps);
835 }
836
837 ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
838 static_cast<long long>(timeUs),
839 static_cast<long long>(mPrevCaptureUs),
840 static_cast<long long>(mPrevFrameUs));
841 } else {
842 if (timeUs <= mPrevFrameUs) {
843 if (mFrameDropper != NULL && mFrameDropper->disabled()) {
844 // Warn only, client has disabled frame drop logic possibly for image
845 // encoding cases where camera's ZSL mode could send out of order frames.
846 ALOGW("Received frame that's going backward in time");
847 } else {
848 // Drop the frame if it's going backward in time. Bad timestamp
849 // could disrupt encoder's rate control completely.
850 ALOGW("Dropping frame that's going backward in time");
851 return false;
852 }
853 }
854
855 mPrevFrameUs = timeUs;
856 }
857
858 *codecTimeUs = mPrevFrameUs;
859 return true;
860 }
861
submitBuffer_l(const VideoBuffer & item)862 status_t GraphicBufferSource::submitBuffer_l(const VideoBuffer &item) {
863 CHECK(!mFreeCodecBuffers.empty());
864 uint32_t codecBufferId = *mFreeCodecBuffers.begin();
865
866 ALOGV("submitBuffer_l [slot=%d, bufferId=%d]", item.mBuffer->getSlot(), codecBufferId);
867
868 int64_t codecTimeUs;
869 if (!calculateCodecTimestamp_l(item.mTimestampNs, &codecTimeUs)) {
870 return UNKNOWN_ERROR;
871 }
872
873 if ((android_dataspace)item.mDataspace != mLastDataspace) {
874 onDataspaceChanged_l(
875 item.mDataspace,
876 (android_pixel_format)item.mBuffer->getGraphicBuffer()->format);
877 }
878
879 std::shared_ptr<AcquiredBuffer> buffer = item.mBuffer;
880 // use a GraphicBuffer for now as component is using GraphicBuffers to hold references
881 // and it requires this graphic buffer to be able to hold its reference
882 // and thus we would need to create a new GraphicBuffer from an ANWBuffer separate from the
883 // acquired GraphicBuffer.
884 // TODO: this can be reworked globally to use ANWBuffer references
885 sp<GraphicBuffer> graphicBuffer = buffer->getGraphicBuffer();
886 status_t err = mComponent->submitBuffer(
887 codecBufferId, graphicBuffer, codecTimeUs, buffer->getAcquireFenceFd());
888
889 if (err != OK) {
890 ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err);
891 return err;
892 }
893
894 mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
895
896 ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, buffer);
897 ALOGV("emptyGraphicBuffer succeeded, bufferId=%u@%zd bufhandle=%p",
898 codecBufferId, cbix, graphicBuffer->handle);
899 return OK;
900 }
901
submitEndOfInputStream_l()902 void GraphicBufferSource::submitEndOfInputStream_l() {
903 CHECK(mEndOfStream);
904 if (mEndOfStreamSent) {
905 ALOGV("EOS already sent");
906 return;
907 }
908
909 if (mFreeCodecBuffers.empty()) {
910 ALOGV("submitEndOfInputStream_l: no codec buffers available");
911 return;
912 }
913 uint32_t codecBufferId = *mFreeCodecBuffers.begin();
914
915 // We reject any additional incoming graphic buffers. There is no acquired buffer used for EOS
916 status_t err = mComponent->submitEos(codecBufferId);
917 if (err != OK) {
918 ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
919 } else {
920 mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
921 ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, nullptr);
922 ALOGV("submitEndOfInputStream_l: buffer submitted, bufferId=%u@%zd", codecBufferId, cbix);
923 mEndOfStreamSent = true;
924
925 // no need to hold onto any buffers for frame repeating
926 ++mRepeatLastFrameGeneration;
927 mLatestBuffer.mBuffer.reset();
928 }
929 }
930
acquireBuffer_l(VideoBuffer * ab)931 status_t GraphicBufferSource::acquireBuffer_l(VideoBuffer *ab) {
932 BufferItem bi;
933 status_t err = mConsumer->acquireBuffer(&bi, 0);
934 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
935 // shouldn't happen
936 ALOGW("acquireBuffer_l: frame was not available");
937 return err;
938 } else if (err != OK) {
939 ALOGW("acquireBuffer_l: failed with err=%d", err);
940 return err;
941 }
942 --mNumAvailableUnacquiredBuffers;
943
944 // Manage our buffer cache.
945 std::shared_ptr<CachedBuffer> buffer;
946 ssize_t bsi = mBufferSlots.indexOfKey(bi.mSlot);
947 if (bi.mGraphicBuffer != NULL) {
948 // replace/initialize slot with new buffer
949 ALOGV("acquireBuffer_l: %s buffer slot %d", bsi < 0 ? "setting" : "UPDATING", bi.mSlot);
950 if (bsi >= 0) {
951 discardBufferAtSlotIndex_l(bsi);
952 } else {
953 bsi = mBufferSlots.add(bi.mSlot, nullptr);
954 }
955 buffer = std::make_shared<CachedBuffer>(bi.mSlot, bi.mGraphicBuffer);
956 mBufferSlots.replaceValueAt(bsi, buffer);
957 } else {
958 buffer = mBufferSlots.valueAt(bsi);
959 }
960 int64_t frameNum = bi.mFrameNumber;
961
962 std::shared_ptr<AcquiredBuffer> acquiredBuffer =
963 std::make_shared<AcquiredBuffer>(
964 buffer,
965 [frameNum, this](AcquiredBuffer *buffer){
966 // AcquiredBuffer's destructor should always be called when mMutex is locked.
967 // If we had a reentrant mutex, we could just lock it again to ensure this.
968 if (mMutex.tryLock() == 0) {
969 TRESPASS_DBG();
970 mMutex.unlock();
971 }
972
973 // we can release buffers immediately if not using adapters
974 // alternately, we could add them to mSlotsToRelease, but we would
975 // somehow need to propagate frame number to that queue
976 if (buffer->isCached()) {
977 --mNumOutstandingAcquires;
978 mConsumer->releaseBuffer(
979 buffer->getSlot(), frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
980 buffer->getReleaseFence());
981 }
982 },
983 bi.mFence);
984 VideoBuffer videoBuffer{acquiredBuffer, bi.mTimestamp, bi.mDataSpace};
985 *ab = videoBuffer;
986 ++mNumOutstandingAcquires;
987 return OK;
988 }
989
990 // BufferQueue::ConsumerListener callback
onFrameAvailable(const BufferItem & item __unused)991 void GraphicBufferSource::onFrameAvailable(const BufferItem& item __unused) {
992 Mutex::Autolock autoLock(mMutex);
993
994 ALOGV("onFrameAvailable: executing=%d available=%zu+%d",
995 mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
996 ++mNumAvailableUnacquiredBuffers;
997
998 // For BufferQueue we cannot acquire a buffer if we cannot immediately feed it to the codec
999 // UNLESS we are discarding this buffer (acquiring and immediately releasing it), which makes
1000 // this an ugly logic.
1001 // NOTE: We could also rely on our debug counter but that is meant only as a debug counter.
1002 if (!areWeDiscardingAvailableBuffers_l() && mFreeCodecBuffers.empty()) {
1003 // we may not be allowed to acquire a possibly encodable buffer, so just note that
1004 // it is available
1005 ALOGV("onFrameAvailable: cannot acquire buffer right now, do it later");
1006
1007 ++mRepeatLastFrameGeneration; // cancel any pending frame repeat
1008 return;
1009 }
1010
1011 VideoBuffer buffer;
1012 status_t err = acquireBuffer_l(&buffer);
1013 if (err != OK) {
1014 ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err);
1015 } else {
1016 onBufferAcquired_l(buffer);
1017 }
1018 }
1019
areWeDiscardingAvailableBuffers_l()1020 bool GraphicBufferSource::areWeDiscardingAvailableBuffers_l() {
1021 return mEndOfStreamSent // already sent EOS to codec
1022 || mComponent == nullptr // there is no codec connected
1023 || (mSuspended && mActionQueue.empty()) // we are suspended and not waiting for
1024 // any further action
1025 || !mExecuting;
1026 }
1027
onBufferAcquired_l(const VideoBuffer & buffer)1028 void GraphicBufferSource::onBufferAcquired_l(const VideoBuffer &buffer) {
1029 if (mEndOfStreamSent) {
1030 // This should only be possible if a new buffer was queued after
1031 // EOS was signaled, i.e. the app is misbehaving.
1032 ALOGW("onFrameAvailable: EOS is sent, ignoring frame");
1033 } else if (mComponent == NULL || (mSuspended && mActionQueue.empty())) {
1034 // FIXME: if we are suspended but have a resume queued we will stop repeating the last
1035 // frame. Is that the desired behavior?
1036 ALOGV("onFrameAvailable: suspended, ignoring frame");
1037 } else {
1038 ++mRepeatLastFrameGeneration; // cancel any pending frame repeat
1039 mAvailableBuffers.push_back(buffer);
1040 if (mExecuting) {
1041 fillCodecBuffer_l();
1042 }
1043 }
1044 }
1045
1046 // BufferQueue::ConsumerListener callback
onBuffersReleased()1047 void GraphicBufferSource::onBuffersReleased() {
1048 Mutex::Autolock lock(mMutex);
1049
1050 uint64_t slotMask;
1051 uint64_t releaseMask;
1052 if (mConsumer->getReleasedBuffers(&releaseMask) != NO_ERROR) {
1053 slotMask = 0xffffffffffffffffULL;
1054 ALOGW("onBuffersReleased: unable to get released buffer set");
1055 } else {
1056 slotMask = releaseMask;
1057 ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
1058 }
1059
1060 AString unpopulated;
1061 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
1062 if ((slotMask & 0x01) != 0) {
1063 if (!discardBufferInSlot_l(i)) {
1064 if (!unpopulated.empty()) {
1065 unpopulated.append(", ");
1066 }
1067 unpopulated.append(i);
1068 }
1069 }
1070 slotMask >>= 1;
1071 }
1072 if (!unpopulated.empty()) {
1073 ALOGW("released unpopulated slots: [%s]", unpopulated.c_str());
1074 }
1075 }
1076
discardBufferInSlot_l(GraphicBufferSource::slot_id i)1077 bool GraphicBufferSource::discardBufferInSlot_l(GraphicBufferSource::slot_id i) {
1078 ssize_t bsi = mBufferSlots.indexOfKey(i);
1079 if (bsi < 0) {
1080 return false;
1081 } else {
1082 discardBufferAtSlotIndex_l(bsi);
1083 mBufferSlots.removeItemsAt(bsi);
1084 return true;
1085 }
1086 }
1087
discardBufferAtSlotIndex_l(ssize_t bsi)1088 void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t bsi) {
1089 const std::shared_ptr<CachedBuffer>& buffer = mBufferSlots.valueAt(bsi);
1090 // use -2 if there is no latest buffer, and -1 if it is no longer cached
1091 slot_id latestBufferSlot =
1092 mLatestBuffer.mBuffer == nullptr ? -2 : mLatestBuffer.mBuffer->getSlot();
1093 ALOGV("releasing acquired buffer: [slot=%d, useCount=%ld], latest: [slot=%d]",
1094 mBufferSlots.keyAt(bsi), buffer.use_count(), latestBufferSlot);
1095 mBufferSlots.valueAt(bsi)->onDroppedFromCache();
1096
1097 // If the slot of an acquired buffer is discarded, that buffer will not have to be
1098 // released to the producer, so account it here. However, it is possible that the
1099 // acquired buffer has already been discarded so check if it still is.
1100 if (buffer->isAcquired()) {
1101 --mNumOutstandingAcquires;
1102 }
1103
1104 // clear the buffer reference (not technically needed as caller either replaces or deletes
1105 // it; done here for safety).
1106 mBufferSlots.editValueAt(bsi).reset();
1107 CHECK_DBG(buffer == nullptr);
1108 }
1109
releaseAllAvailableBuffers_l()1110 void GraphicBufferSource::releaseAllAvailableBuffers_l() {
1111 mAvailableBuffers.clear();
1112 while (mNumAvailableUnacquiredBuffers > 0) {
1113 VideoBuffer item;
1114 if (acquireBuffer_l(&item) != OK) {
1115 ALOGW("releaseAllAvailableBuffers: failed to acquire available unacquired buffer");
1116 break;
1117 }
1118 }
1119 }
1120
1121 // BufferQueue::ConsumerListener callback
onSidebandStreamChanged()1122 void GraphicBufferSource::onSidebandStreamChanged() {
1123 ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
1124 }
1125
configure(const sp<ComponentWrapper> & component,int32_t dataSpace,int32_t bufferCount,uint32_t frameWidth,uint32_t frameHeight,uint32_t consumerUsage)1126 status_t GraphicBufferSource::configure(
1127 const sp<ComponentWrapper>& component,
1128 int32_t dataSpace,
1129 int32_t bufferCount,
1130 uint32_t frameWidth,
1131 uint32_t frameHeight,
1132 uint32_t consumerUsage) {
1133 if (component == NULL) {
1134 return BAD_VALUE;
1135 }
1136
1137
1138 // Call setMaxAcquiredBufferCount without lock.
1139 // setMaxAcquiredBufferCount could call back to onBuffersReleased
1140 // if the buffer count change results in releasing of existing buffers,
1141 // which would lead to deadlock.
1142 status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
1143 if (err != NO_ERROR) {
1144 ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
1145 bufferCount, err);
1146 return err;
1147 }
1148
1149 {
1150 Mutex::Autolock autoLock(mMutex);
1151 mComponent = component;
1152
1153 err = mConsumer->setDefaultBufferSize(frameWidth, frameHeight);
1154 if (err != NO_ERROR) {
1155 ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
1156 frameWidth, frameHeight, err);
1157 return err;
1158 }
1159
1160 consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
1161 mConsumer->setConsumerUsageBits(consumerUsage);
1162
1163 // Set impl. defined format as default. Depending on the usage flags
1164 // the device-specific implementation will derive the exact format.
1165 err = mConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
1166 if (err != NO_ERROR) {
1167 ALOGE("Failed to configure surface default format ret: %d", err);
1168 return err;
1169 }
1170
1171 // Sets the default buffer data space
1172 ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires);
1173 mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
1174 mLastDataspace = (android_dataspace)dataSpace;
1175
1176 mExecuting = false;
1177 mSuspended = false;
1178 mEndOfStream = false;
1179 mEndOfStreamSent = false;
1180 mSkipFramesBeforeNs = -1LL;
1181 mFrameDropper.clear();
1182 mFrameRepeatIntervalUs = -1LL;
1183 mRepeatLastFrameGeneration = 0;
1184 mOutstandingFrameRepeatCount = 0;
1185 mLatestBuffer.mBuffer.reset();
1186 mFrameRepeatBlockedOnCodecBuffer = false;
1187 mFps = -1.0;
1188 mCaptureFps = -1.0;
1189 mBaseCaptureUs = -1LL;
1190 mBaseFrameUs = -1LL;
1191 mPrevCaptureUs = -1LL;
1192 mPrevFrameUs = -1LL;
1193 mFrameCount = 0;
1194 mInputBufferTimeOffsetUs = 0;
1195 mStopTimeUs = -1;
1196 mActionQueue.clear();
1197 }
1198
1199 return OK;
1200 }
1201
setSuspend(bool suspend,int64_t suspendStartTimeUs)1202 status_t GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
1203 ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs);
1204
1205 Mutex::Autolock autoLock(mMutex);
1206
1207 if (mStopTimeUs != -1) {
1208 ALOGE("setSuspend failed as STOP action is pending");
1209 return INVALID_OPERATION;
1210 }
1211
1212 // Push the action to the queue.
1213 if (suspendStartTimeUs != -1) {
1214 // suspendStartTimeUs must be smaller or equal to current systemTime.
1215 int64_t currentSystemTimeUs = systemTime() / 1000;
1216 if (suspendStartTimeUs > currentSystemTimeUs) {
1217 ALOGE("setSuspend failed. %lld is larger than current system time %lld us",
1218 (long long)suspendStartTimeUs, (long long)currentSystemTimeUs);
1219 return INVALID_OPERATION;
1220 }
1221 if (mLastActionTimeUs != -1 && suspendStartTimeUs < mLastActionTimeUs) {
1222 ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
1223 (long long)suspendStartTimeUs, (long long)mLastActionTimeUs);
1224 return INVALID_OPERATION;
1225 }
1226 mLastActionTimeUs = suspendStartTimeUs;
1227 ActionItem action;
1228 action.mAction = suspend ? ActionItem::PAUSE : ActionItem::RESUME;
1229 action.mActionTimeUs = suspendStartTimeUs;
1230 ALOGV("Push %s action into actionQueue", suspend ? "PAUSE" : "RESUME");
1231 mActionQueue.push_back(action);
1232 } else {
1233 if (suspend) {
1234 mSuspended = true;
1235 releaseAllAvailableBuffers_l();
1236 return OK;
1237 } else {
1238 mSuspended = false;
1239 if (mExecuting && !haveAvailableBuffers_l()
1240 && mFrameRepeatBlockedOnCodecBuffer) {
1241 if (repeatLatestBuffer_l()) {
1242 ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
1243 mFrameRepeatBlockedOnCodecBuffer = false;
1244 } else {
1245 ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
1246 }
1247 }
1248 }
1249 }
1250 return OK;
1251 }
1252
setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs)1253 status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
1254 ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs);
1255
1256 Mutex::Autolock autoLock(mMutex);
1257
1258 if (mExecuting || repeatAfterUs <= 0LL) {
1259 return INVALID_OPERATION;
1260 }
1261
1262 mFrameRepeatIntervalUs = repeatAfterUs;
1263 return OK;
1264 }
1265
setTimeOffsetUs(int64_t timeOffsetUs)1266 status_t GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
1267 Mutex::Autolock autoLock(mMutex);
1268
1269 // timeOffsetUs must be negative for adjustment.
1270 if (timeOffsetUs >= 0LL) {
1271 return INVALID_OPERATION;
1272 }
1273
1274 mInputBufferTimeOffsetUs = timeOffsetUs;
1275 return OK;
1276 }
1277
setMaxFps(float maxFps)1278 status_t GraphicBufferSource::setMaxFps(float maxFps) {
1279 ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps);
1280
1281 Mutex::Autolock autoLock(mMutex);
1282
1283 if (mExecuting) {
1284 return INVALID_OPERATION;
1285 }
1286
1287 mFrameDropper = new FrameDropper();
1288 status_t err = mFrameDropper->setMaxFrameRate(maxFps);
1289 if (err != OK) {
1290 mFrameDropper.clear();
1291 return err;
1292 }
1293
1294 return OK;
1295 }
1296
setStartTimeUs(int64_t skipFramesBeforeUs)1297 status_t GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
1298 ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs);
1299
1300 Mutex::Autolock autoLock(mMutex);
1301
1302 mSkipFramesBeforeNs =
1303 (skipFramesBeforeUs > 0 && skipFramesBeforeUs <= INT64_MAX / 1000) ?
1304 (skipFramesBeforeUs * 1000) : -1LL;
1305
1306 return OK;
1307 }
1308
setStopTimeUs(int64_t stopTimeUs)1309 status_t GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
1310 ALOGV("setStopTimeUs: %lld us", (long long)stopTimeUs);
1311 Mutex::Autolock autoLock(mMutex);
1312
1313 if (mStopTimeUs != -1) {
1314 // Ignore if stop time has already been set
1315 return OK;
1316 }
1317
1318 // stopTimeUs must be smaller or equal to current systemTime.
1319 int64_t currentSystemTimeUs = systemTime() / 1000;
1320 if (stopTimeUs > currentSystemTimeUs) {
1321 ALOGE("setStopTimeUs failed. %lld is larger than current system time %lld us",
1322 (long long)stopTimeUs, (long long)currentSystemTimeUs);
1323 return INVALID_OPERATION;
1324 }
1325 if (mLastActionTimeUs != -1 && stopTimeUs < mLastActionTimeUs) {
1326 ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
1327 (long long)stopTimeUs, (long long)mLastActionTimeUs);
1328 return INVALID_OPERATION;
1329 }
1330 mLastActionTimeUs = stopTimeUs;
1331 ActionItem action;
1332 action.mAction = ActionItem::STOP;
1333 action.mActionTimeUs = stopTimeUs;
1334 mActionQueue.push_back(action);
1335 mStopTimeUs = stopTimeUs;
1336 return OK;
1337 }
1338
getStopTimeOffsetUs(int64_t * stopTimeOffsetUs)1339 status_t GraphicBufferSource::getStopTimeOffsetUs(int64_t *stopTimeOffsetUs) {
1340 ALOGV("getStopTimeOffsetUs");
1341 Mutex::Autolock autoLock(mMutex);
1342 if (mStopTimeUs == -1) {
1343 ALOGW("Fail to return stopTimeOffsetUs as stop time is not set");
1344 return INVALID_OPERATION;
1345 }
1346 *stopTimeOffsetUs =
1347 mLastFrameTimestampUs == -1 ? 0 : mStopTimeUs - mLastFrameTimestampUs;
1348 return OK;
1349 }
1350
setTimeLapseConfig(double fps,double captureFps)1351 status_t GraphicBufferSource::setTimeLapseConfig(double fps, double captureFps) {
1352 ALOGV("setTimeLapseConfig: fps=%lg, captureFps=%lg",
1353 fps, captureFps);
1354 Mutex::Autolock autoLock(mMutex);
1355
1356 if (mExecuting || !(fps > 0) || !(captureFps > 0)) {
1357 return INVALID_OPERATION;
1358 }
1359
1360 mFps = fps;
1361 mCaptureFps = captureFps;
1362
1363 return OK;
1364 }
1365
setColorAspects(int32_t aspectsPacked)1366 status_t GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
1367 Mutex::Autolock autoLock(mMutex);
1368 mDefaultColorAspectsPacked = aspectsPacked;
1369 ColorAspects colorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
1370 ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
1371 colorAspects.mRange, asString(colorAspects.mRange),
1372 colorAspects.mPrimaries, asString(colorAspects.mPrimaries),
1373 colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs),
1374 colorAspects.mTransfer, asString(colorAspects.mTransfer));
1375
1376 return OK;
1377 }
1378
signalEndOfInputStream()1379 status_t GraphicBufferSource::signalEndOfInputStream() {
1380 Mutex::Autolock autoLock(mMutex);
1381 ALOGV("signalEndOfInputStream: executing=%d available=%zu+%d eos=%d",
1382 mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream);
1383
1384 if (mEndOfStream) {
1385 ALOGE("EOS was already signaled");
1386 return INVALID_OPERATION;
1387 }
1388
1389 // Set the end-of-stream flag. If no frames are pending from the
1390 // BufferQueue, and a codec buffer is available, and we're executing,
1391 // and there is no stop timestamp, we initiate the EOS from here.
1392 // Otherwise, we'll let codecBufferEmptied() (or start) do it.
1393 //
1394 // Note: if there are no pending frames and all codec buffers are
1395 // available, we *must* submit the EOS from here or we'll just
1396 // stall since no future events are expected.
1397 mEndOfStream = true;
1398
1399 if (mStopTimeUs == -1 && mExecuting && !haveAvailableBuffers_l()) {
1400 submitEndOfInputStream_l();
1401 }
1402
1403 return OK;
1404 }
1405
onMessageReceived(const sp<AMessage> & msg)1406 void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
1407 switch (msg->what()) {
1408 case kWhatRepeatLastFrame:
1409 {
1410 Mutex::Autolock autoLock(mMutex);
1411
1412 int32_t generation;
1413 CHECK(msg->findInt32("generation", &generation));
1414
1415 if (generation != mRepeatLastFrameGeneration) {
1416 // stale
1417 break;
1418 }
1419
1420 if (!mExecuting || haveAvailableBuffers_l()) {
1421 break;
1422 }
1423
1424 bool success = repeatLatestBuffer_l();
1425 if (success) {
1426 ALOGV("repeatLatestBuffer_l SUCCESS");
1427 } else {
1428 ALOGV("repeatLatestBuffer_l FAILURE");
1429 mFrameRepeatBlockedOnCodecBuffer = true;
1430 }
1431 break;
1432 }
1433
1434 default:
1435 TRESPASS();
1436 }
1437 }
1438
1439 } // namespace android
1440