Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 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 | |
Mark Salyzyn | db43b34 | 2014-04-04 14:47:28 -0700 | [diff] [blame] | 17 | #include <inttypes.h> |
| 18 | |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 19 | #define LOG_TAG "GraphicBufferSource" |
Yin-Chia Yeh | b392112 | 2017-04-18 15:52:55 -0700 | [diff] [blame] | 20 | //#define LOG_NDEBUG 0 |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 21 | #include <utils/Log.h> |
| 22 | |
Lajos Molnar | b77d03b | 2016-03-03 14:02:17 -0800 | [diff] [blame] | 23 | #define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h |
| 24 | |
Wonsik Kim | 82832ce | 2018-01-26 17:43:53 -0800 | [diff] [blame] | 25 | #include <media/stagefright/bqhelper/GraphicBufferSource.h> |
| 26 | #include <media/stagefright/bqhelper/FrameDropper.h> |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 27 | #include <media/stagefright/foundation/ADebug.h> |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 28 | #include <media/stagefright/foundation/AMessage.h> |
Lajos Molnar | b77d03b | 2016-03-03 14:02:17 -0800 | [diff] [blame] | 29 | #include <media/stagefright/foundation/ColorUtils.h> |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 30 | #include <media/stagefright/foundation/FileDescriptor.h> |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 31 | |
Pawin Vongmasa | ee9bde7 | 2019-09-11 09:59:08 -0700 | [diff] [blame] | 32 | #include <android-base/properties.h> |
Mathias Agopian | 5e1f08b | 2013-07-16 22:54:39 -0700 | [diff] [blame] | 33 | #include <media/hardware/MetadataBufferType.h> |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 34 | #include <ui/GraphicBuffer.h> |
Dan Stoza | 8ed8ced | 2015-03-12 15:19:45 -0700 | [diff] [blame] | 35 | #include <gui/BufferItem.h> |
Chong Zhang | 0e4c08e | 2019-04-19 10:00:45 -0700 | [diff] [blame] | 36 | #include <gui/BufferQueue.h> |
| 37 | #include <gui/bufferqueue/1.0/WGraphicBufferProducer.h> |
Chong Zhang | c8ce1d8 | 2019-03-27 10:18:38 -0700 | [diff] [blame] | 38 | #include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h> |
Chong Zhang | 0e4c08e | 2019-04-19 10:00:45 -0700 | [diff] [blame] | 39 | #include <gui/IGraphicBufferProducer.h> |
| 40 | #include <gui/IGraphicBufferConsumer.h> |
Pawin Vongmasa | 255735a | 2017-07-19 11:24:56 -0700 | [diff] [blame] | 41 | #include <media/hardware/HardwareAPI.h> |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 42 | |
Dan Stoza | 2475264 | 2014-04-09 16:10:53 -0700 | [diff] [blame] | 43 | #include <inttypes.h> |
| 44 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 45 | #include <functional> |
| 46 | #include <memory> |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 47 | #include <cmath> |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 48 | |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 49 | namespace android { |
| 50 | |
Pawin Vongmasa | 4082162 | 2017-11-14 20:09:38 -0800 | [diff] [blame] | 51 | namespace { |
| 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. |
| 78 | constexpr double kTimestampFluctuation = 0.05; |
| 79 | } |
| 80 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 81 | /** |
| 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 | */ |
| 88 | struct 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 | |
| 142 | private: |
| 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 | */ |
| 169 | struct 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 | |
| 262 | private: |
| 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 Zhang | 0fe4c47 | 2019-04-08 21:51:46 +0000 | [diff] [blame] | 290 | struct GraphicBufferSource::ConsumerProxy : public BufferQueue::ConsumerListener { |
Chong Zhang | 768fc2d | 2019-04-15 11:54:59 -0700 | [diff] [blame] | 291 | ConsumerProxy(const wp<GraphicBufferSource> &gbs) : mGbs(gbs) {} |
Chong Zhang | 0fe4c47 | 2019-04-08 21:51:46 +0000 | [diff] [blame] | 292 | |
| 293 | ~ConsumerProxy() = default; |
| 294 | |
| 295 | void onFrameAvailable(const BufferItem& item) override { |
Chong Zhang | 768fc2d | 2019-04-15 11:54:59 -0700 | [diff] [blame] | 296 | sp<GraphicBufferSource> gbs = mGbs.promote(); |
| 297 | if (gbs != nullptr) { |
| 298 | gbs->onFrameAvailable(item); |
| 299 | } |
Chong Zhang | 0fe4c47 | 2019-04-08 21:51:46 +0000 | [diff] [blame] | 300 | } |
| 301 | |
| 302 | void onBuffersReleased() override { |
Chong Zhang | 768fc2d | 2019-04-15 11:54:59 -0700 | [diff] [blame] | 303 | sp<GraphicBufferSource> gbs = mGbs.promote(); |
| 304 | if (gbs != nullptr) { |
| 305 | gbs->onBuffersReleased(); |
| 306 | } |
Chong Zhang | 0fe4c47 | 2019-04-08 21:51:46 +0000 | [diff] [blame] | 307 | } |
| 308 | |
| 309 | void onSidebandStreamChanged() override { |
Chong Zhang | 768fc2d | 2019-04-15 11:54:59 -0700 | [diff] [blame] | 310 | sp<GraphicBufferSource> gbs = mGbs.promote(); |
| 311 | if (gbs != nullptr) { |
| 312 | gbs->onSidebandStreamChanged(); |
| 313 | } |
Chong Zhang | 0fe4c47 | 2019-04-08 21:51:46 +0000 | [diff] [blame] | 314 | } |
| 315 | |
| 316 | private: |
Chong Zhang | 768fc2d | 2019-04-15 11:54:59 -0700 | [diff] [blame] | 317 | // 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 Zhang | 0fe4c47 | 2019-04-08 21:51:46 +0000 | [diff] [blame] | 321 | }; |
| 322 | |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 323 | GraphicBufferSource::GraphicBufferSource() : |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 324 | mInitCheck(UNKNOWN_ERROR), |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 325 | mNumAvailableUnacquiredBuffers(0), |
| 326 | mNumOutstandingAcquires(0), |
| 327 | mEndOfStream(false), |
| 328 | mEndOfStreamSent(false), |
| 329 | mLastDataspace(HAL_DATASPACE_UNKNOWN), |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 330 | mExecuting(false), |
Andreas Huber | e40cda7 | 2013-07-17 13:55:26 -0700 | [diff] [blame] | 331 | mSuspended(false), |
Hangyu Kuang | f72cefd | 2017-04-05 11:07:08 -0700 | [diff] [blame] | 332 | mLastFrameTimestampUs(-1), |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 333 | mStopTimeUs(-1), |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 334 | mLastActionTimeUs(-1LL), |
| 335 | mSkipFramesBeforeNs(-1LL), |
| 336 | mFrameRepeatIntervalUs(-1LL), |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 337 | mRepeatLastFrameGeneration(0), |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 338 | mOutstandingFrameRepeatCount(0), |
| 339 | mFrameRepeatBlockedOnCodecBuffer(false), |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 340 | mFps(-1.0), |
| 341 | mCaptureFps(-1.0), |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 342 | mBaseCaptureUs(-1LL), |
| 343 | mBaseFrameUs(-1LL), |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 344 | mFrameCount(0), |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 345 | mPrevCaptureUs(-1LL), |
| 346 | mPrevFrameUs(-1LL), |
| 347 | mInputBufferTimeOffsetUs(0LL) { |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 348 | ALOGV("GraphicBufferSource"); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 349 | |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 350 | String8 name("GraphicBufferSource"); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 351 | |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 352 | BufferQueue::createBufferQueue(&mProducer, &mConsumer); |
| 353 | mConsumer->setConsumerName(name); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 354 | |
Chong Zhang | 0fe4c47 | 2019-04-08 21:51:46 +0000 | [diff] [blame] | 355 | // 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 Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 359 | sp<IConsumerListener> proxy = |
Chong Zhang | 0fe4c47 | 2019-04-08 21:51:46 +0000 | [diff] [blame] | 360 | new BufferQueue::ProxyConsumerListener(mConsumerProxy); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 361 | |
Dan Stoza | 5205977 | 2014-03-12 15:07:30 -0700 | [diff] [blame] | 362 | mInitCheck = mConsumer->consumerConnect(proxy, false); |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 363 | if (mInitCheck != NO_ERROR) { |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 364 | ALOGE("Error connecting to BufferQueue: %s (%d)", |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 365 | strerror(-mInitCheck), mInitCheck); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 366 | return; |
| 367 | } |
| 368 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 369 | memset(&mDefaultColorAspectsPacked, 0, sizeof(mDefaultColorAspectsPacked)); |
Lajos Molnar | dd81af7 | 2016-03-10 18:19:18 -0800 | [diff] [blame] | 370 | |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 371 | CHECK(mInitCheck == NO_ERROR); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 372 | } |
| 373 | |
| 374 | GraphicBufferSource::~GraphicBufferSource() { |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 375 | ALOGV("~GraphicBufferSource"); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 376 | { |
| 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 Zhang | 9700f5f | 2015-06-12 18:30:08 -0700 | [diff] [blame] | 383 | } |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 384 | |
| 385 | if (mNumOutstandingAcquires != 0) { |
| 386 | ALOGW("potential buffer leak: acquired=%d", mNumOutstandingAcquires); |
| 387 | TRESPASS_DBG(); |
Chong Zhang | 9700f5f | 2015-06-12 18:30:08 -0700 | [diff] [blame] | 388 | } |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 389 | if (mConsumer != NULL) { |
Dan Stoza | 5205977 | 2014-03-12 15:07:30 -0700 | [diff] [blame] | 390 | status_t err = mConsumer->consumerDisconnect(); |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 391 | if (err != NO_ERROR) { |
| 392 | ALOGW("consumerDisconnect failed: %d", err); |
| 393 | } |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 394 | } |
| 395 | } |
| 396 | |
Chong Zhang | 0e4c08e | 2019-04-19 10:00:45 -0700 | [diff] [blame] | 397 | sp<IGraphicBufferProducer> GraphicBufferSource::getIGraphicBufferProducer() const { |
| 398 | return mProducer; |
| 399 | } |
| 400 | |
| 401 | sp<::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer> |
| 402 | GraphicBufferSource::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 Zhang | c8ce1d8 | 2019-03-27 10:18:38 -0700 | [diff] [blame] | 409 | sp<::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer> |
| 410 | GraphicBufferSource::getHGraphicBufferProducer() const { |
| 411 | return new ::android::hardware::graphics::bufferqueue::V2_0::utils:: |
| 412 | B2HGraphicBufferProducer(getIGraphicBufferProducer()); |
| 413 | } |
| 414 | |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 415 | status_t GraphicBufferSource::start() { |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 416 | Mutex::Autolock autoLock(mMutex); |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 417 | ALOGV("--> start; available=%zu, submittable=%zd", |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 418 | mAvailableBuffers.size(), mFreeCodecBuffers.size()); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 419 | CHECK(!mExecuting); |
| 420 | mExecuting = true; |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 421 | mLastDataspace = HAL_DATASPACE_UNKNOWN; |
Lajos Molnar | b77d03b | 2016-03-03 14:02:17 -0800 | [diff] [blame] | 422 | ALOGV("clearing last dataSpace"); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 423 | |
| 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 Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 433 | while (haveAvailableBuffers_l()) { |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 434 | if (!fillCodecBuffer_l()) { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 435 | ALOGV("stop load with available=%zu+%d", |
| 436 | mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 437 | break; |
| 438 | } |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 439 | } |
| 440 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 441 | ALOGV("done loading initial frames, available=%zu+%d", |
| 442 | mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 443 | |
| 444 | // If EOS has already been signaled, and there are no more frames to |
| 445 | // submit, try to send EOS now as well. |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 446 | if (mStopTimeUs == -1 && mEndOfStream && !haveAvailableBuffers_l()) { |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 447 | submitEndOfInputStream_l(); |
| 448 | } |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 449 | |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 450 | if (mFrameRepeatIntervalUs > 0LL && mLooper == NULL) { |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 451 | mReflector = new AHandlerReflector<GraphicBufferSource>(this); |
| 452 | |
| 453 | mLooper = new ALooper; |
| 454 | mLooper->registerHandler(mReflector); |
| 455 | mLooper->start(); |
| 456 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 457 | if (mLatestBuffer.mBuffer != nullptr) { |
| 458 | queueFrameRepeat_l(); |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 459 | } |
| 460 | } |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 461 | |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 462 | return OK; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 463 | } |
| 464 | |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 465 | status_t GraphicBufferSource::stop() { |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 466 | ALOGV("stop"); |
Andreas Huber | ad3b7e8 | 2013-11-07 11:13:27 -0800 | [diff] [blame] | 467 | |
| 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 Huber | 892e1b9 | 2013-11-08 10:57:34 -0800 | [diff] [blame] | 473 | mExecuting = false; |
Andreas Huber | ad3b7e8 | 2013-11-07 11:13:27 -0800 | [diff] [blame] | 474 | } |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 475 | return OK; |
Andreas Huber | ad3b7e8 | 2013-11-07 11:13:27 -0800 | [diff] [blame] | 476 | } |
| 477 | |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 478 | status_t GraphicBufferSource::release(){ |
Pawin Vongmasa | 2b0ee67 | 2018-03-08 16:19:07 -0800 | [diff] [blame] | 479 | 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 Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 486 | |
Pawin Vongmasa | 2b0ee67 | 2018-03-08 16:19:07 -0800 | [diff] [blame] | 487 | 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 Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 500 | } |
Pawin Vongmasa | 2b0ee67 | 2018-03-08 16:19:07 -0800 | [diff] [blame] | 501 | if (looper != NULL) { |
| 502 | looper->stop(); |
| 503 | } |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 504 | return OK; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 505 | } |
| 506 | |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 507 | status_t GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) { |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 508 | 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 Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 514 | return INVALID_OPERATION; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 515 | } |
| 516 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 517 | ALOGV("addCodecBuffer: bufferId=%u", bufferId); |
Chong Zhang | 6cf9a12 | 2016-09-08 23:25:52 -0700 | [diff] [blame] | 518 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 519 | mFreeCodecBuffers.push_back(bufferId); |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 520 | return OK; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 521 | } |
| 522 | |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 523 | status_t GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) { |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 524 | Mutex::Autolock autoLock(mMutex); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 525 | FileDescriptor::Autoclose fence(fenceFd); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 526 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 527 | ssize_t cbi = mSubmittedCodecBuffers.indexOfKey(bufferId); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 528 | if (cbi < 0) { |
| 529 | // This should never happen. |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 530 | ALOGE("onInputBufferEmptied: buffer not recognized (bufferId=%u)", bufferId); |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 531 | return BAD_VALUE; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 532 | } |
| 533 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 534 | 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 McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 539 | |
| 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 Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 542 | // see if there is a null AcquiredBuffer, which should only ever happen for EOS. |
| 543 | if (buffer == nullptr) { |
Andy McFadden | 5572b3a | 2013-11-07 14:39:03 -0800 | [diff] [blame] | 544 | if (!(mEndOfStream && mEndOfStreamSent)) { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 545 | // 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 McFadden | 5572b3a | 2013-11-07 14:39:03 -0800 | [diff] [blame] | 549 | } |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 550 | // No GraphicBuffer to deal with, no additional input or output is expected, so just return. |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 551 | return BAD_VALUE; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 552 | } |
| 553 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 554 | 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 Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 557 | return OK; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 558 | } |
| 559 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 560 | 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 McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 563 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 564 | 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 McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 569 | // Fill this codec buffer. |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 570 | CHECK(!mEndOfStreamSent); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 571 | ALOGV("onInputBufferEmptied: buffer freed, feeding codec (available=%zu+%d, eos=%d)", |
| 572 | mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 573 | fillCodecBuffer_l(); |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 574 | } else if (mEndOfStream && mStopTimeUs == -1) { |
| 575 | // No frames available, but EOS is pending and no stop time, so use this buffer to |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 576 | // send that. |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 577 | ALOGV("onInputBufferEmptied: buffer freed, submitting EOS"); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 578 | submitEndOfInputStream_l(); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 579 | } else if (mFrameRepeatBlockedOnCodecBuffer) { |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 580 | bool success = repeatLatestBuffer_l(); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 581 | ALOGV("onInputBufferEmptied: completing deferred repeatLatestBuffer_l %s", |
| 582 | success ? "SUCCESS" : "FAILURE"); |
| 583 | mFrameRepeatBlockedOnCodecBuffer = false; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 584 | } |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 585 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 586 | // releaseReleasableBuffers_l(); |
Chong Zhang | d1bbbe3 | 2020-01-15 17:13:01 -0800 | [diff] [blame] | 587 | return OK; |
Andreas Huber | e40cda7 | 2013-07-17 13:55:26 -0700 | [diff] [blame] | 588 | } |
| 589 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 590 | void GraphicBufferSource::onDataspaceChanged_l( |
| 591 | android_dataspace dataspace, android_pixel_format pixelFormat) { |
guochuang | f677f7c | 2023-05-09 20:28:27 +0800 | [diff] [blame^] | 592 | ALOGD("got buffer with new dataSpace %#x", dataspace); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 593 | mLastDataspace = dataspace; |
Lajos Molnar | b77d03b | 2016-03-03 14:02:17 -0800 | [diff] [blame] | 594 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 595 | if (ColorUtils::convertDataSpaceToV0(dataspace)) { |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 596 | mComponent->dispatchDataSpaceChanged( |
| 597 | mLastDataspace, mDefaultColorAspectsPacked, pixelFormat); |
Lajos Molnar | b77d03b | 2016-03-03 14:02:17 -0800 | [diff] [blame] | 598 | } |
| 599 | } |
| 600 | |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 601 | bool GraphicBufferSource::fillCodecBuffer_l() { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 602 | CHECK(mExecuting && haveAvailableBuffers_l()); |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 603 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 604 | if (mFreeCodecBuffers.empty()) { |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 605 | // No buffers available, bail. |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 606 | ALOGV("fillCodecBuffer_l: no codec buffers, available=%zu+%d", |
| 607 | mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 608 | return false; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 609 | } |
| 610 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 611 | 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 McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 624 | } |
| 625 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 626 | int64_t itemTimeUs = item.mTimestampNs / 1000; |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 627 | |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 628 | // 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 Kuang | 384cd77 | 2017-03-20 16:15:37 -0700 | [diff] [blame] | 635 | // [pause 1us], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 636 | // 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 Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 638 | bool done = false; |
Hangyu Kuang | 21bafd5 | 2017-03-30 12:39:38 -0700 | [diff] [blame] | 639 | bool seeStopAction = false; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 640 | 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 Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 649 | done = true; |
| 650 | } |
| 651 | |
| 652 | if (!done) { |
Hangyu Kuang | 384cd77 | 2017-03-20 16:15:37 -0700 | [diff] [blame] | 653 | // Find the newest action that with timestamp smaller than itemTimeUs. Then |
| 654 | // remove all the actions before and include the newest action. |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 655 | List<ActionItem>::iterator it = mActionQueue.begin(); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 656 | while (it != mActionQueue.end() && it->mActionTimeUs <= itemTimeUs |
| 657 | && nextAction.mAction != ActionItem::STOP) { |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 658 | nextAction = *it; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 659 | ++it; |
| 660 | } |
Hangyu Kuang | 384cd77 | 2017-03-20 16:15:37 -0700 | [diff] [blame] | 661 | mActionQueue.erase(mActionQueue.begin(), it); |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 662 | |
| 663 | CHECK(itemTimeUs >= nextAction.mActionTimeUs); |
| 664 | switch (nextAction.mAction) { |
| 665 | case ActionItem::PAUSE: |
| 666 | { |
| 667 | mSuspended = true; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 668 | 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 Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 683 | // Clear the whole ActionQueue as recording is done |
| 684 | mActionQueue.clear(); |
Hangyu Kuang | 21bafd5 | 2017-03-30 12:39:38 -0700 | [diff] [blame] | 685 | seeStopAction = true; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 686 | break; |
| 687 | } |
| 688 | default: |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 689 | TRESPASS_DBG("Unknown action type"); |
| 690 | // return true here because we did consume an available buffer, so the |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 691 | // loop in start will eventually terminate even if we hit this. |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 692 | return false; |
| 693 | } |
| 694 | } |
| 695 | } |
| 696 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 697 | if (seeStopAction) { |
| 698 | // Clear all the buffers before setting mEndOfStream and signal EndOfInputStream. |
| 699 | releaseAllAvailableBuffers_l(); |
| 700 | mEndOfStream = true; |
| 701 | submitEndOfInputStream_l(); |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 702 | return true; |
| 703 | } |
| 704 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 705 | if (mSuspended) { |
| 706 | return true; |
Lajos Molnar | b77d03b | 2016-03-03 14:02:17 -0800 | [diff] [blame] | 707 | } |
| 708 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 709 | int err = UNKNOWN_ERROR; |
Chong Zhang | 72cecca | 2013-12-26 01:38:35 -0800 | [diff] [blame] | 710 | |
| 711 | // only submit sample if start time is unspecified, or sample |
| 712 | // is queued after the specified start time |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 713 | if (mSkipFramesBeforeNs < 0LL || item.mTimestampNs >= mSkipFramesBeforeNs) { |
Chong Zhang | 72cecca | 2013-12-26 01:38:35 -0800 | [diff] [blame] | 714 | // if start time is set, offset time stamp by start time |
| 715 | if (mSkipFramesBeforeNs > 0) { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 716 | item.mTimestampNs -= mSkipFramesBeforeNs; |
Chong Zhang | 72cecca | 2013-12-26 01:38:35 -0800 | [diff] [blame] | 717 | } |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 718 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 719 | int64_t timeUs = item.mTimestampNs / 1000; |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 720 | 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 Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 724 | } else { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 725 | err = submitBuffer_l(item); // this takes shared ownership of the acquired buffer on succeess |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 726 | } |
Chong Zhang | 72cecca | 2013-12-26 01:38:35 -0800 | [diff] [blame] | 727 | } |
| 728 | |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 729 | if (err != OK) { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 730 | ALOGV("submitBuffer_l failed, will release bq slot %d", item.mBuffer->getSlot()); |
| 731 | return true; |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 732 | } else { |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 733 | // 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 Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 735 | if (mFrameRepeatIntervalUs > 0LL) { |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 736 | setLatestBuffer_l(item); |
| 737 | } |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 738 | ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d", |
| 739 | item.mBuffer->getSlot(), item.mBuffer.use_count(), mNumOutstandingAcquires); |
Hangyu Kuang | fd871c7 | 2017-04-28 10:11:19 -0700 | [diff] [blame] | 740 | mLastFrameTimestampUs = itemTimeUs; |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 741 | } |
| 742 | |
| 743 | return true; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 744 | } |
| 745 | |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 746 | bool GraphicBufferSource::repeatLatestBuffer_l() { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 747 | CHECK(mExecuting && !haveAvailableBuffers_l()); |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 748 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 749 | if (mLatestBuffer.mBuffer == nullptr || mSuspended) { |
Andy McFadden | bdfd488 | 2013-10-23 13:39:43 -0700 | [diff] [blame] | 750 | return false; |
| 751 | } |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 752 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 753 | if (mFreeCodecBuffers.empty()) { |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 754 | // No buffers available, bail. |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 755 | ALOGV("repeatLatestBuffer_l: no codec buffers."); |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 756 | return false; |
| 757 | } |
| 758 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 759 | if (!mLatestBuffer.mBuffer->isCached()) { |
| 760 | ALOGV("repeatLatestBuffer_l: slot was discarded, but repeating our own reference"); |
| 761 | } |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 762 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 763 | // 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 Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 765 | if (err != OK) { |
| 766 | return false; |
| 767 | } |
| 768 | |
Chong Zhang | 94ee4b7 | 2014-01-10 17:36:57 -0800 | [diff] [blame] | 769 | /* 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 Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 773 | if (--mOutstandingFrameRepeatCount > 0) { |
| 774 | // set up timestamp for repeat frame |
| 775 | mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000; |
| 776 | queueFrameRepeat_l(); |
Chong Zhang | 94ee4b7 | 2014-01-10 17:36:57 -0800 | [diff] [blame] | 777 | } |
| 778 | |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 779 | return true; |
| 780 | } |
| 781 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 782 | void GraphicBufferSource::setLatestBuffer_l(const VideoBuffer &item) { |
| 783 | mLatestBuffer = item; |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 784 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 785 | ALOGV("setLatestBuffer_l: [slot=%d, useCount=%ld]", |
| 786 | mLatestBuffer.mBuffer->getSlot(), mLatestBuffer.mBuffer.use_count()); |
Chong Zhang | 94ee4b7 | 2014-01-10 17:36:57 -0800 | [diff] [blame] | 787 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 788 | mOutstandingFrameRepeatCount = kRepeatLastFrameCount; |
| 789 | // set up timestamp for repeat frame |
| 790 | mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000; |
| 791 | queueFrameRepeat_l(); |
| 792 | } |
Chong Zhang | fdeac6c | 2016-09-14 17:57:57 -0700 | [diff] [blame] | 793 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 794 | void GraphicBufferSource::queueFrameRepeat_l() { |
| 795 | mFrameRepeatBlockedOnCodecBuffer = false; |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 796 | |
| 797 | if (mReflector != NULL) { |
Lajos Molnar | 1d15ab5 | 2015-03-04 16:46:34 -0800 | [diff] [blame] | 798 | sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector); |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 799 | msg->setInt32("generation", ++mRepeatLastFrameGeneration); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 800 | msg->post(mFrameRepeatIntervalUs); |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 801 | } |
| 802 | } |
| 803 | |
Pawin Vongmasa | ee9bde7 | 2019-09-11 09:59:08 -0700 | [diff] [blame] | 804 | #ifdef __clang__ |
| 805 | __attribute__((no_sanitize("integer"))) |
| 806 | #endif |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 807 | bool GraphicBufferSource::calculateCodecTimestamp_l( |
| 808 | nsecs_t bufferTimeNs, int64_t *codecTimeUs) { |
| 809 | int64_t timeUs = bufferTimeNs / 1000; |
Hangyu Kuang | 61fcfd1 | 2016-08-30 13:50:58 -0700 | [diff] [blame] | 810 | timeUs += mInputBufferTimeOffsetUs; |
Chong Zhang | 94ee4b7 | 2014-01-10 17:36:57 -0800 | [diff] [blame] | 811 | |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 812 | if (mCaptureFps > 0. |
| 813 | && (mFps > 2 * mCaptureFps |
| 814 | || mCaptureFps > 2 * mFps)) { |
Chong Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 815 | // Time lapse or slow motion mode |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 816 | if (mPrevCaptureUs < 0LL) { |
Chong Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 817 | // first capture |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 818 | mPrevCaptureUs = mBaseCaptureUs = timeUs; |
Hangyu Kuang | bd83e4b | 2016-10-26 13:56:11 -0700 | [diff] [blame] | 819 | // adjust the first sample timestamp. |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 820 | mPrevFrameUs = mBaseFrameUs = |
| 821 | std::llround((timeUs * mCaptureFps) / mFps); |
| 822 | mFrameCount = 0; |
Pawin Vongmasa | ee9bde7 | 2019-09-11 09:59:08 -0700 | [diff] [blame] | 823 | } else if (mSnapTimestamps) { |
Pawin Vongmasa | 4082162 | 2017-11-14 20:09:38 -0800 | [diff] [blame] | 824 | double nFrames = (timeUs - mPrevCaptureUs) * mCaptureFps / 1000000; |
| 825 | if (nFrames < 0.5 - kTimestampFluctuation) { |
Chong Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 826 | // skip this frame as it's too close to previous capture |
Pawin Vongmasa | ee9bde7 | 2019-09-11 09:59:08 -0700 | [diff] [blame] | 827 | ALOGD("skipping frame, timeUs %lld", |
| 828 | static_cast<long long>(timeUs)); |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 829 | return false; |
Chong Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 830 | } |
Pawin Vongmasa | ee9bde7 | 2019-09-11 09:59:08 -0700 | [diff] [blame] | 831 | // snap to nearest capture point |
Pawin Vongmasa | 4082162 | 2017-11-14 20:09:38 -0800 | [diff] [blame] | 832 | if (nFrames <= 1.0) { |
| 833 | nFrames = 1.0; |
| 834 | } |
| 835 | mFrameCount += std::llround(nFrames); |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 836 | mPrevCaptureUs = mBaseCaptureUs + std::llround( |
Pawin Vongmasa | 780882d | 2017-08-16 03:47:16 -0700 | [diff] [blame] | 837 | mFrameCount * 1000000 / mCaptureFps); |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 838 | mPrevFrameUs = mBaseFrameUs + std::llround( |
Pawin Vongmasa | 780882d | 2017-08-16 03:47:16 -0700 | [diff] [blame] | 839 | mFrameCount * 1000000 / mFps); |
Pawin Vongmasa | ee9bde7 | 2019-09-11 09:59:08 -0700 | [diff] [blame] | 840 | } 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 Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 856 | } |
| 857 | |
| 858 | ALOGV("timeUs %lld, captureUs %lld, frameUs %lld", |
Mark Salyzyn | a5750e0 | 2014-06-18 16:34:45 -0700 | [diff] [blame] | 859 | static_cast<long long>(timeUs), |
| 860 | static_cast<long long>(mPrevCaptureUs), |
| 861 | static_cast<long long>(mPrevFrameUs)); |
Hangyu Kuang | 61fcfd1 | 2016-08-30 13:50:58 -0700 | [diff] [blame] | 862 | } else { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 863 | if (timeUs <= mPrevFrameUs) { |
Chong Zhang | 6c2d0ad | 2018-05-24 19:36:53 -0700 | [diff] [blame] | 864 | 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 Zhang | 94ee4b7 | 2014-01-10 17:36:57 -0800 | [diff] [blame] | 874 | } |
Hangyu Kuang | 61fcfd1 | 2016-08-30 13:50:58 -0700 | [diff] [blame] | 875 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 876 | mPrevFrameUs = timeUs; |
Chong Zhang | 94ee4b7 | 2014-01-10 17:36:57 -0800 | [diff] [blame] | 877 | } |
| 878 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 879 | *codecTimeUs = mPrevFrameUs; |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 880 | return true; |
Chong Zhang | 94ee4b7 | 2014-01-10 17:36:57 -0800 | [diff] [blame] | 881 | } |
| 882 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 883 | status_t GraphicBufferSource::submitBuffer_l(const VideoBuffer &item) { |
| 884 | CHECK(!mFreeCodecBuffers.empty()); |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 885 | uint32_t codecBufferId = *mFreeCodecBuffers.begin(); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 886 | |
| 887 | ALOGV("submitBuffer_l [slot=%d, bufferId=%d]", item.mBuffer->getSlot(), codecBufferId); |
Chong Zhang | b63d243 | 2014-02-14 15:26:00 -0800 | [diff] [blame] | 888 | |
Chong Zhang | 3604cb1 | 2016-10-10 12:08:11 -0700 | [diff] [blame] | 889 | int64_t codecTimeUs; |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 890 | if (!calculateCodecTimestamp_l(item.mTimestampNs, &codecTimeUs)) { |
Chong Zhang | b63d243 | 2014-02-14 15:26:00 -0800 | [diff] [blame] | 891 | return UNKNOWN_ERROR; |
| 892 | } |
| 893 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 894 | if ((android_dataspace)item.mDataspace != mLastDataspace) { |
| 895 | onDataspaceChanged_l( |
| 896 | item.mDataspace, |
| 897 | (android_pixel_format)item.mBuffer->getGraphicBuffer()->format); |
| 898 | } |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 899 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 900 | std::shared_ptr<AcquiredBuffer> buffer = item.mBuffer; |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 901 | // use a GraphicBuffer for now as component is using GraphicBuffers to hold references |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 902 | // 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 Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 907 | status_t err = mComponent->submitBuffer( |
| 908 | codecBufferId, graphicBuffer, codecTimeUs, buffer->getAcquireFenceFd()); |
Chong Zhang | 6cf9a12 | 2016-09-08 23:25:52 -0700 | [diff] [blame] | 909 | |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 910 | if (err != OK) { |
Chong Zhang | 6cf9a12 | 2016-09-08 23:25:52 -0700 | [diff] [blame] | 911 | ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 912 | return err; |
| 913 | } |
| 914 | |
Lajos Molnar | 195f1ed | 2017-04-26 15:19:47 -0700 | [diff] [blame] | 915 | mFreeCodecBuffers.erase(mFreeCodecBuffers.begin()); |
| 916 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 917 | ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, buffer); |
| 918 | ALOGV("emptyGraphicBuffer succeeded, bufferId=%u@%zd bufhandle=%p", |
| 919 | codecBufferId, cbix, graphicBuffer->handle); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 920 | return OK; |
| 921 | } |
| 922 | |
| 923 | void GraphicBufferSource::submitEndOfInputStream_l() { |
| 924 | CHECK(mEndOfStream); |
| 925 | if (mEndOfStreamSent) { |
| 926 | ALOGV("EOS already sent"); |
| 927 | return; |
| 928 | } |
| 929 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 930 | if (mFreeCodecBuffers.empty()) { |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 931 | ALOGV("submitEndOfInputStream_l: no codec buffers available"); |
| 932 | return; |
| 933 | } |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 934 | uint32_t codecBufferId = *mFreeCodecBuffers.begin(); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 935 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 936 | // We reject any additional incoming graphic buffers. There is no acquired buffer used for EOS |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 937 | status_t err = mComponent->submitEos(codecBufferId); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 938 | if (err != OK) { |
| 939 | ALOGW("emptyDirectBuffer EOS failed: 0x%x", err); |
| 940 | } else { |
Lajos Molnar | 195f1ed | 2017-04-26 15:19:47 -0700 | [diff] [blame] | 941 | mFreeCodecBuffers.erase(mFreeCodecBuffers.begin()); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 942 | ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, nullptr); |
| 943 | ALOGV("submitEndOfInputStream_l: buffer submitted, bufferId=%u@%zd", codecBufferId, cbix); |
Andy McFadden | 0c37f9d | 2013-03-11 15:09:32 -0700 | [diff] [blame] | 944 | mEndOfStreamSent = true; |
Lajos Molnar | 1f0fa90 | 2017-06-05 12:42:17 -0700 | [diff] [blame] | 945 | |
| 946 | // no need to hold onto any buffers for frame repeating |
| 947 | ++mRepeatLastFrameGeneration; |
| 948 | mLatestBuffer.mBuffer.reset(); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 949 | } |
| 950 | } |
| 951 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 952 | status_t GraphicBufferSource::acquireBuffer_l(VideoBuffer *ab) { |
| 953 | BufferItem bi; |
| 954 | status_t err = mConsumer->acquireBuffer(&bi, 0); |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 955 | if (err == BufferQueue::NO_BUFFER_AVAILABLE) { |
| 956 | // shouldn't happen |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 957 | ALOGW("acquireBuffer_l: frame was not available"); |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 958 | return err; |
| 959 | } else if (err != OK) { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 960 | ALOGW("acquireBuffer_l: failed with err=%d", err); |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 961 | return err; |
| 962 | } |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 963 | --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 Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 980 | } |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 981 | 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 Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1008 | return OK; |
| 1009 | } |
| 1010 | |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1011 | // BufferQueue::ConsumerListener callback |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1012 | void GraphicBufferSource::onFrameAvailable(const BufferItem& item __unused) { |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1013 | Mutex::Autolock autoLock(mMutex); |
| 1014 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1015 | ALOGV("onFrameAvailable: executing=%d available=%zu+%d", |
| 1016 | mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); |
| 1017 | ++mNumAvailableUnacquiredBuffers; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1018 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1019 | // For BufferQueue we cannot acquire a buffer if we cannot immediately feed it to the codec |
Lajos Molnar | 02cccfd | 2017-04-25 18:08:42 -0700 | [diff] [blame] | 1020 | // UNLESS we are discarding this buffer (acquiring and immediately releasing it), which makes |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1021 | // 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 Huber | e40cda7 | 2013-07-17 13:55:26 -0700 | [diff] [blame] | 1027 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1028 | ++mRepeatLastFrameGeneration; // cancel any pending frame repeat |
Lajos Molnar | 02cccfd | 2017-04-25 18:08:42 -0700 | [diff] [blame] | 1029 | return; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1030 | } |
| 1031 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1032 | 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 McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1040 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1041 | bool GraphicBufferSource::areWeDiscardingAvailableBuffers_l() { |
| 1042 | return mEndOfStreamSent // already sent EOS to codec |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 1043 | || mComponent == nullptr // there is no codec connected |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1044 | || (mSuspended && mActionQueue.empty()) // we are suspended and not waiting for |
| 1045 | // any further action |
| 1046 | || !mExecuting; |
| 1047 | } |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1048 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1049 | void 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 Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 1054 | } else if (mComponent == NULL || (mSuspended && mActionQueue.empty())) { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1055 | // 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 McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1064 | } |
| 1065 | } |
| 1066 | |
| 1067 | // BufferQueue::ConsumerListener callback |
| 1068 | void GraphicBufferSource::onBuffersReleased() { |
| 1069 | Mutex::Autolock lock(mMutex); |
| 1070 | |
Dan Stoza | 2475264 | 2014-04-09 16:10:53 -0700 | [diff] [blame] | 1071 | uint64_t slotMask; |
Lajos Molnar | 1357839 | 2017-09-12 14:20:10 -0700 | [diff] [blame] | 1072 | uint64_t releaseMask; |
| 1073 | if (mConsumer->getReleasedBuffers(&releaseMask) != NO_ERROR) { |
Dan Stoza | 2475264 | 2014-04-09 16:10:53 -0700 | [diff] [blame] | 1074 | slotMask = 0xffffffffffffffffULL; |
Lajos Molnar | 1357839 | 2017-09-12 14:20:10 -0700 | [diff] [blame] | 1075 | ALOGW("onBuffersReleased: unable to get released buffer set"); |
| 1076 | } else { |
| 1077 | slotMask = releaseMask; |
| 1078 | ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask); |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1079 | } |
| 1080 | |
Lajos Molnar | 1357839 | 2017-09-12 14:20:10 -0700 | [diff] [blame] | 1081 | AString unpopulated; |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1082 | for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { |
| 1083 | if ((slotMask & 0x01) != 0) { |
Lajos Molnar | 1357839 | 2017-09-12 14:20:10 -0700 | [diff] [blame] | 1084 | if (!discardBufferInSlot_l(i)) { |
| 1085 | if (!unpopulated.empty()) { |
| 1086 | unpopulated.append(", "); |
| 1087 | } |
| 1088 | unpopulated.append(i); |
| 1089 | } |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1090 | } |
| 1091 | slotMask >>= 1; |
| 1092 | } |
Lajos Molnar | 1357839 | 2017-09-12 14:20:10 -0700 | [diff] [blame] | 1093 | if (!unpopulated.empty()) { |
| 1094 | ALOGW("released unpopulated slots: [%s]", unpopulated.c_str()); |
| 1095 | } |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1096 | } |
| 1097 | |
Lajos Molnar | 1357839 | 2017-09-12 14:20:10 -0700 | [diff] [blame] | 1098 | bool GraphicBufferSource::discardBufferInSlot_l(GraphicBufferSource::slot_id i) { |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1099 | ssize_t bsi = mBufferSlots.indexOfKey(i); |
| 1100 | if (bsi < 0) { |
Lajos Molnar | 1357839 | 2017-09-12 14:20:10 -0700 | [diff] [blame] | 1101 | return false; |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1102 | } else { |
| 1103 | discardBufferAtSlotIndex_l(bsi); |
| 1104 | mBufferSlots.removeItemsAt(bsi); |
Lajos Molnar | 1357839 | 2017-09-12 14:20:10 -0700 | [diff] [blame] | 1105 | return true; |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1106 | } |
| 1107 | } |
| 1108 | |
| 1109 | void 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 | |
| 1131 | void 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 Hall | 8dcc81a | 2014-03-03 15:35:36 -0800 | [diff] [blame] | 1142 | // BufferQueue::ConsumerListener callback |
| 1143 | void GraphicBufferSource::onSidebandStreamChanged() { |
| 1144 | ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams"); |
| 1145 | } |
| 1146 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1147 | status_t GraphicBufferSource::configure( |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 1148 | const sp<ComponentWrapper>& component, |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1149 | int32_t dataSpace, |
| 1150 | int32_t bufferCount, |
| 1151 | uint32_t frameWidth, |
| 1152 | uint32_t frameHeight, |
| 1153 | uint32_t consumerUsage) { |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 1154 | if (component == NULL) { |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1155 | return BAD_VALUE; |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1156 | } |
| 1157 | |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1158 | |
| 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 Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1163 | status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount); |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1164 | if (err != NO_ERROR) { |
| 1165 | ALOGE("Unable to set BQ max acquired buffer count to %u: %d", |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1166 | bufferCount, err); |
| 1167 | return err; |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1168 | } |
| 1169 | |
| 1170 | { |
| 1171 | Mutex::Autolock autoLock(mMutex); |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 1172 | mComponent = component; |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1173 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1174 | err = mConsumer->setDefaultBufferSize(frameWidth, frameHeight); |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1175 | if (err != NO_ERROR) { |
| 1176 | ALOGE("Unable to set BQ default buffer size to %ux%u: %d", |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1177 | frameWidth, frameHeight, err); |
| 1178 | return err; |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1179 | } |
| 1180 | |
| 1181 | consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER; |
| 1182 | mConsumer->setConsumerUsageBits(consumerUsage); |
| 1183 | |
Emilian Peev | 9ff0327 | 2018-10-11 19:03:49 +0100 | [diff] [blame] | 1184 | // 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 Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1192 | // Sets the default buffer data space |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1193 | ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires); |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1194 | mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1195 | mLastDataspace = (android_dataspace)dataSpace; |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1196 | |
| 1197 | mExecuting = false; |
| 1198 | mSuspended = false; |
| 1199 | mEndOfStream = false; |
| 1200 | mEndOfStreamSent = false; |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 1201 | mSkipFramesBeforeNs = -1LL; |
Chong Zhang | 6c2d0ad | 2018-05-24 19:36:53 -0700 | [diff] [blame] | 1202 | mFrameDropper.clear(); |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 1203 | mFrameRepeatIntervalUs = -1LL; |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1204 | mRepeatLastFrameGeneration = 0; |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1205 | mOutstandingFrameRepeatCount = 0; |
| 1206 | mLatestBuffer.mBuffer.reset(); |
| 1207 | mFrameRepeatBlockedOnCodecBuffer = false; |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 1208 | mFps = -1.0; |
| 1209 | mCaptureFps = -1.0; |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 1210 | mBaseCaptureUs = -1LL; |
| 1211 | mBaseFrameUs = -1LL; |
| 1212 | mPrevCaptureUs = -1LL; |
| 1213 | mPrevFrameUs = -1LL; |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 1214 | mFrameCount = 0; |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1215 | mInputBufferTimeOffsetUs = 0; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1216 | mStopTimeUs = -1; |
| 1217 | mActionQueue.clear(); |
Chong Zhang | addf2cb | 2016-09-28 17:53:01 -0700 | [diff] [blame] | 1218 | } |
| 1219 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1220 | return OK; |
Lajos Molnar | 57fad3c | 2016-03-08 13:09:35 -0800 | [diff] [blame] | 1221 | } |
| 1222 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1223 | status_t GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) { |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1224 | ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs); |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1225 | |
| 1226 | Mutex::Autolock autoLock(mMutex); |
| 1227 | |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1228 | if (mStopTimeUs != -1) { |
| 1229 | ALOGE("setSuspend failed as STOP action is pending"); |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1230 | return INVALID_OPERATION; |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1231 | } |
| 1232 | |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1233 | // 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 Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1240 | return INVALID_OPERATION; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1241 | } |
| 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 Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1245 | return INVALID_OPERATION; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1246 | } |
| 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 Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1256 | releaseAllAvailableBuffers_l(); |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1257 | return OK; |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1258 | } else { |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1259 | mSuspended = false; |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1260 | if (mExecuting && !haveAvailableBuffers_l() |
| 1261 | && mFrameRepeatBlockedOnCodecBuffer) { |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1262 | if (repeatLatestBuffer_l()) { |
| 1263 | ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS"); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1264 | mFrameRepeatBlockedOnCodecBuffer = false; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1265 | } else { |
| 1266 | ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE"); |
| 1267 | } |
| 1268 | } |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1269 | } |
| 1270 | } |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1271 | return OK; |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1272 | } |
| 1273 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1274 | status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) { |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1275 | ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs); |
| 1276 | |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1277 | Mutex::Autolock autoLock(mMutex); |
| 1278 | |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 1279 | if (mExecuting || repeatAfterUs <= 0LL) { |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1280 | return INVALID_OPERATION; |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1281 | } |
| 1282 | |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1283 | mFrameRepeatIntervalUs = repeatAfterUs; |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1284 | return OK; |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1285 | } |
| 1286 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1287 | status_t GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) { |
Hangyu Kuang | 61fcfd1 | 2016-08-30 13:50:58 -0700 | [diff] [blame] | 1288 | Mutex::Autolock autoLock(mMutex); |
| 1289 | |
| 1290 | // timeOffsetUs must be negative for adjustment. |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 1291 | if (timeOffsetUs >= 0LL) { |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1292 | return INVALID_OPERATION; |
Hangyu Kuang | 61fcfd1 | 2016-08-30 13:50:58 -0700 | [diff] [blame] | 1293 | } |
| 1294 | |
| 1295 | mInputBufferTimeOffsetUs = timeOffsetUs; |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1296 | return OK; |
Hangyu Kuang | 61fcfd1 | 2016-08-30 13:50:58 -0700 | [diff] [blame] | 1297 | } |
| 1298 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1299 | status_t GraphicBufferSource::setMaxFps(float maxFps) { |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1300 | ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps); |
| 1301 | |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 1302 | Mutex::Autolock autoLock(mMutex); |
| 1303 | |
| 1304 | if (mExecuting) { |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1305 | return INVALID_OPERATION; |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 1306 | } |
| 1307 | |
| 1308 | mFrameDropper = new FrameDropper(); |
| 1309 | status_t err = mFrameDropper->setMaxFrameRate(maxFps); |
| 1310 | if (err != OK) { |
| 1311 | mFrameDropper.clear(); |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1312 | return err; |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 1313 | } |
| 1314 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1315 | return OK; |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 1316 | } |
| 1317 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1318 | status_t GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) { |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1319 | ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs); |
| 1320 | |
Chong Zhang | 72cecca | 2013-12-26 01:38:35 -0800 | [diff] [blame] | 1321 | Mutex::Autolock autoLock(mMutex); |
| 1322 | |
| 1323 | mSkipFramesBeforeNs = |
Pawin Vongmasa | 3a75f04 | 2017-11-08 04:44:59 -0800 | [diff] [blame] | 1324 | (skipFramesBeforeUs > 0 && skipFramesBeforeUs <= INT64_MAX / 1000) ? |
Chih-Hung Hsieh | 3794b24 | 2018-12-11 13:55:06 -0800 | [diff] [blame] | 1325 | (skipFramesBeforeUs * 1000) : -1LL; |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1326 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1327 | return OK; |
Chong Zhang | 72cecca | 2013-12-26 01:38:35 -0800 | [diff] [blame] | 1328 | } |
| 1329 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1330 | status_t GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) { |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1331 | 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 Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1336 | return OK; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1337 | } |
| 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 Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1344 | return INVALID_OPERATION; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1345 | } |
| 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 Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1349 | return INVALID_OPERATION; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1350 | } |
| 1351 | mLastActionTimeUs = stopTimeUs; |
| 1352 | ActionItem action; |
| 1353 | action.mAction = ActionItem::STOP; |
| 1354 | action.mActionTimeUs = stopTimeUs; |
| 1355 | mActionQueue.push_back(action); |
| 1356 | mStopTimeUs = stopTimeUs; |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1357 | return OK; |
Hangyu Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1358 | } |
| 1359 | |
Hangyu Kuang | f72cefd | 2017-04-05 11:07:08 -0700 | [diff] [blame] | 1360 | status_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 Kuang | cf3205f | 2017-06-20 11:25:06 -0700 | [diff] [blame] | 1367 | *stopTimeOffsetUs = |
| 1368 | mLastFrameTimestampUs == -1 ? 0 : mStopTimeUs - mLastFrameTimestampUs; |
Hangyu Kuang | f72cefd | 2017-04-05 11:07:08 -0700 | [diff] [blame] | 1369 | return OK; |
| 1370 | } |
| 1371 | |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 1372 | status_t GraphicBufferSource::setTimeLapseConfig(double fps, double captureFps) { |
| 1373 | ALOGV("setTimeLapseConfig: fps=%lg, captureFps=%lg", |
| 1374 | fps, captureFps); |
Chong Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 1375 | Mutex::Autolock autoLock(mMutex); |
| 1376 | |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 1377 | if (mExecuting || !(fps > 0) || !(captureFps > 0)) { |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1378 | return INVALID_OPERATION; |
Chong Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 1379 | } |
| 1380 | |
Pawin Vongmasa | 22dc508 | 2017-04-20 05:12:55 -0700 | [diff] [blame] | 1381 | mFps = fps; |
| 1382 | mCaptureFps = captureFps; |
Pawin Vongmasa | ee9bde7 | 2019-09-11 09:59:08 -0700 | [diff] [blame] | 1383 | if (captureFps > fps) { |
| 1384 | mSnapTimestamps = 1 == base::GetIntProperty( |
Pawin Vongmasa | def61c9 | 2019-09-20 16:53:03 -0700 | [diff] [blame] | 1385 | "debug.stagefright.snap_timestamps", int64_t(0)); |
Pawin Vongmasa | ee9bde7 | 2019-09-11 09:59:08 -0700 | [diff] [blame] | 1386 | } else { |
| 1387 | mSnapTimestamps = false; |
| 1388 | } |
Chong Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 1389 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1390 | return OK; |
Chong Zhang | 2c9c8cb | 2014-02-11 13:54:59 -0800 | [diff] [blame] | 1391 | } |
| 1392 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1393 | status_t GraphicBufferSource::setColorAspects(int32_t aspectsPacked) { |
Lajos Molnar | dd81af7 | 2016-03-10 18:19:18 -0800 | [diff] [blame] | 1394 | Mutex::Autolock autoLock(mMutex); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1395 | mDefaultColorAspectsPacked = aspectsPacked; |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1396 | ColorAspects colorAspects = ColorUtils::unpackToColorAspects(aspectsPacked); |
Lajos Molnar | b77d03b | 2016-03-03 14:02:17 -0800 | [diff] [blame] | 1397 | ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))", |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1398 | colorAspects.mRange, asString(colorAspects.mRange), |
| 1399 | colorAspects.mPrimaries, asString(colorAspects.mPrimaries), |
| 1400 | colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs), |
| 1401 | colorAspects.mTransfer, asString(colorAspects.mTransfer)); |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1402 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1403 | return OK; |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1404 | } |
| 1405 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1406 | status_t GraphicBufferSource::signalEndOfInputStream() { |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1407 | Mutex::Autolock autoLock(mMutex); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1408 | ALOGV("signalEndOfInputStream: executing=%d available=%zu+%d eos=%d", |
| 1409 | mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream); |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1410 | |
| 1411 | if (mEndOfStream) { |
| 1412 | ALOGE("EOS was already signaled"); |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1413 | return INVALID_OPERATION; |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1414 | } |
| 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 Kuang | 764d945 | 2016-12-13 13:07:45 -0800 | [diff] [blame] | 1418 | // and there is no stop timestamp, we initiate the EOS from here. |
Wonsik Kim | 2860573 | 2018-01-11 17:11:11 -0800 | [diff] [blame] | 1419 | // Otherwise, we'll let codecBufferEmptied() (or start) do it. |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1420 | // |
| 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 | |
hkuang | 90874e3 | 2020-03-17 09:46:49 -0700 | [diff] [blame] | 1426 | if (mStopTimeUs == -1 && mExecuting && !haveAvailableBuffers_l()) { |
Chong Zhang | 6d332d2 | 2016-09-07 12:06:50 -0700 | [diff] [blame] | 1427 | submitEndOfInputStream_l(); |
| 1428 | } |
| 1429 | |
Robert Shih | d095e65 | 2017-03-11 01:20:43 +0000 | [diff] [blame] | 1430 | return OK; |
Lajos Molnar | dd81af7 | 2016-03-10 18:19:18 -0800 | [diff] [blame] | 1431 | } |
| 1432 | |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1433 | void 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 Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1447 | if (!mExecuting || haveAvailableBuffers_l()) { |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1448 | break; |
| 1449 | } |
| 1450 | |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 1451 | bool success = repeatLatestBuffer_l(); |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1452 | if (success) { |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 1453 | ALOGV("repeatLatestBuffer_l SUCCESS"); |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1454 | } else { |
Ronghua Wu | 37b2b38 | 2015-01-26 15:47:10 -0800 | [diff] [blame] | 1455 | ALOGV("repeatLatestBuffer_l FAILURE"); |
Lajos Molnar | 43fb79a | 2017-04-06 14:27:17 -0700 | [diff] [blame] | 1456 | mFrameRepeatBlockedOnCodecBuffer = true; |
Andreas Huber | a61285d | 2013-07-31 13:50:42 -0700 | [diff] [blame] | 1457 | } |
| 1458 | break; |
| 1459 | } |
| 1460 | |
| 1461 | default: |
| 1462 | TRESPASS(); |
| 1463 | } |
| 1464 | } |
| 1465 | |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 1466 | } // namespace android |