GraphicBufferSource.cpp revision e580006cd0067109189975c56395d29309d49883
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <inttypes.h>
18
19#define LOG_TAG "GraphicBufferSource"
20//#define LOG_NDEBUG 0
21#include <utils/Log.h>
22
23#include "GraphicBufferSource.h"
24
25#include <OMX_Core.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/AMessage.h>
28
29#include <media/hardware/MetadataBufferType.h>
30#include <ui/GraphicBuffer.h>
31
32#include <inttypes.h>
33
34namespace android {
35
36static const bool EXTRA_CHECK = true;
37
38
39GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance,
40        uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount) :
41    mInitCheck(UNKNOWN_ERROR),
42    mNodeInstance(nodeInstance),
43    mExecuting(false),
44    mSuspended(false),
45    mNumFramesAvailable(0),
46    mEndOfStream(false),
47    mEndOfStreamSent(false),
48    mMaxTimestampGapUs(-1ll),
49    mPrevOriginalTimeUs(-1ll),
50    mPrevModifiedTimeUs(-1ll),
51    mSkipFramesBeforeNs(-1ll),
52    mRepeatAfterUs(-1ll),
53    mRepeatLastFrameGeneration(0),
54    mRepeatLastFrameTimestamp(-1ll),
55    mLatestSubmittedBufferId(-1),
56    mLatestSubmittedBufferFrameNum(0),
57    mLatestSubmittedBufferUseCount(0),
58    mRepeatBufferDeferred(false),
59    mTimePerCaptureUs(-1ll),
60    mTimePerFrameUs(-1ll),
61    mPrevCaptureUs(-1ll),
62    mPrevFrameUs(-1ll) {
63
64    ALOGV("GraphicBufferSource w=%u h=%u c=%u",
65            bufferWidth, bufferHeight, bufferCount);
66
67    if (bufferWidth == 0 || bufferHeight == 0) {
68        ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
69        mInitCheck = BAD_VALUE;
70        return;
71    }
72
73    String8 name("GraphicBufferSource");
74
75    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
76    mConsumer->setConsumerName(name);
77    mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
78    mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
79
80    mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
81    if (mInitCheck != NO_ERROR) {
82        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
83                bufferCount, mInitCheck);
84        return;
85    }
86
87    // Note that we can't create an sp<...>(this) in a ctor that will not keep a
88    // reference once the ctor ends, as that would cause the refcount of 'this'
89    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
90    // that's what we create.
91    wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
92    sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
93
94    mInitCheck = mConsumer->consumerConnect(proxy, false);
95    if (mInitCheck != NO_ERROR) {
96        ALOGE("Error connecting to BufferQueue: %s (%d)",
97                strerror(-mInitCheck), mInitCheck);
98        return;
99    }
100
101    CHECK(mInitCheck == NO_ERROR);
102}
103
104GraphicBufferSource::~GraphicBufferSource() {
105    ALOGV("~GraphicBufferSource");
106    if (mConsumer != NULL) {
107        status_t err = mConsumer->consumerDisconnect();
108        if (err != NO_ERROR) {
109            ALOGW("consumerDisconnect failed: %d", err);
110        }
111    }
112}
113
114void GraphicBufferSource::omxExecuting() {
115    Mutex::Autolock autoLock(mMutex);
116    ALOGV("--> executing; avail=%zu, codec vec size=%zd",
117            mNumFramesAvailable, mCodecBuffers.size());
118    CHECK(!mExecuting);
119    mExecuting = true;
120
121    // Start by loading up as many buffers as possible.  We want to do this,
122    // rather than just submit the first buffer, to avoid a degenerate case:
123    // if all BQ buffers arrive before we start executing, and we only submit
124    // one here, the other BQ buffers will just sit until we get notified
125    // that the codec buffer has been released.  We'd then acquire and
126    // submit a single additional buffer, repeatedly, never using more than
127    // one codec buffer simultaneously.  (We could instead try to submit
128    // all BQ buffers whenever any codec buffer is freed, but if we get the
129    // initial conditions right that will never be useful.)
130    while (mNumFramesAvailable) {
131        if (!fillCodecBuffer_l()) {
132            ALOGV("stop load with frames available (codecAvail=%d)",
133                    isCodecBufferAvailable_l());
134            break;
135        }
136    }
137
138    ALOGV("done loading initial frames, avail=%zu", mNumFramesAvailable);
139
140    // If EOS has already been signaled, and there are no more frames to
141    // submit, try to send EOS now as well.
142    if (mEndOfStream && mNumFramesAvailable == 0) {
143        submitEndOfInputStream_l();
144    }
145
146    if (mRepeatAfterUs > 0ll && mLooper == NULL) {
147        mReflector = new AHandlerReflector<GraphicBufferSource>(this);
148
149        mLooper = new ALooper;
150        mLooper->registerHandler(mReflector);
151        mLooper->start();
152
153        if (mLatestSubmittedBufferId >= 0) {
154            sp<AMessage> msg =
155                new AMessage(kWhatRepeatLastFrame, mReflector->id());
156
157            msg->setInt32("generation", ++mRepeatLastFrameGeneration);
158            msg->post(mRepeatAfterUs);
159        }
160    }
161}
162
163void GraphicBufferSource::omxIdle() {
164    ALOGV("omxIdle");
165
166    Mutex::Autolock autoLock(mMutex);
167
168    if (mExecuting) {
169        // We are only interested in the transition from executing->idle,
170        // not loaded->idle.
171        mExecuting = false;
172    }
173}
174
175void GraphicBufferSource::omxLoaded(){
176    Mutex::Autolock autoLock(mMutex);
177    if (!mExecuting) {
178        // This can happen if something failed very early.
179        ALOGW("Dropped back down to Loaded without Executing");
180    }
181
182    if (mLooper != NULL) {
183        mLooper->unregisterHandler(mReflector->id());
184        mReflector.clear();
185
186        mLooper->stop();
187        mLooper.clear();
188    }
189
190    ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d",
191            mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
192
193    // Codec is no longer executing.  Discard all codec-related state.
194    mCodecBuffers.clear();
195    // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
196    //       are null; complain if not
197
198    mExecuting = false;
199}
200
201void GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) {
202    Mutex::Autolock autoLock(mMutex);
203
204    if (mExecuting) {
205        // This should never happen -- buffers can only be allocated when
206        // transitioning from "loaded" to "idle".
207        ALOGE("addCodecBuffer: buffer added while executing");
208        return;
209    }
210
211    ALOGV("addCodecBuffer h=%p size=%" PRIu32 " p=%p",
212            header, header->nAllocLen, header->pBuffer);
213    CodecBuffer codecBuffer;
214    codecBuffer.mHeader = header;
215    mCodecBuffers.add(codecBuffer);
216}
217
218void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) {
219    Mutex::Autolock autoLock(mMutex);
220
221    if (!mExecuting) {
222        return;
223    }
224
225    int cbi = findMatchingCodecBuffer_l(header);
226    if (cbi < 0) {
227        // This should never happen.
228        ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header);
229        return;
230    }
231
232    ALOGV("codecBufferEmptied h=%p size=%" PRIu32 " filled=%" PRIu32 " p=%p",
233            header, header->nAllocLen, header->nFilledLen,
234            header->pBuffer);
235    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
236
237    // header->nFilledLen may not be the original value, so we can't compare
238    // that to zero to see of this was the EOS buffer.  Instead we just
239    // see if the GraphicBuffer reference was null, which should only ever
240    // happen for EOS.
241    if (codecBuffer.mGraphicBuffer == NULL) {
242        if (!(mEndOfStream && mEndOfStreamSent)) {
243            // This can happen when broken code sends us the same buffer
244            // twice in a row.
245            ALOGE("ERROR: codecBufferEmptied on non-EOS null buffer "
246                    "(buffer emptied twice?)");
247        }
248        // No GraphicBuffer to deal with, no additional input or output is
249        // expected, so just return.
250        return;
251    }
252
253    if (EXTRA_CHECK) {
254        // Pull the graphic buffer handle back out of the buffer, and confirm
255        // that it matches expectations.
256        OMX_U8* data = header->pBuffer;
257        buffer_handle_t bufferHandle;
258        memcpy(&bufferHandle, data + 4, sizeof(buffer_handle_t));
259        if (bufferHandle != codecBuffer.mGraphicBuffer->handle) {
260            // should never happen
261            ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
262                    bufferHandle, codecBuffer.mGraphicBuffer->handle);
263            CHECK(!"codecBufferEmptied: mismatched buffer");
264        }
265    }
266
267    // Find matching entry in our cached copy of the BufferQueue slots.
268    // If we find a match, release that slot.  If we don't, the BufferQueue
269    // has dropped that GraphicBuffer, and there's nothing for us to release.
270    int id = codecBuffer.mBuf;
271    if (mBufferSlot[id] != NULL &&
272        mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
273        ALOGV("cbi %d matches bq slot %d, handle=%p",
274                cbi, id, mBufferSlot[id]->handle);
275
276        if (id == mLatestSubmittedBufferId) {
277            CHECK_GT(mLatestSubmittedBufferUseCount--, 0);
278        } else {
279            mConsumer->releaseBuffer(id, codecBuffer.mFrameNumber,
280                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
281        }
282    } else {
283        ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
284                cbi);
285    }
286
287    // Mark the codec buffer as available by clearing the GraphicBuffer ref.
288    codecBuffer.mGraphicBuffer = NULL;
289
290    if (mNumFramesAvailable) {
291        // Fill this codec buffer.
292        CHECK(!mEndOfStreamSent);
293        ALOGV("buffer freed, %zu frames avail (eos=%d)",
294                mNumFramesAvailable, mEndOfStream);
295        fillCodecBuffer_l();
296    } else if (mEndOfStream) {
297        // No frames available, but EOS is pending, so use this buffer to
298        // send that.
299        ALOGV("buffer freed, EOS pending");
300        submitEndOfInputStream_l();
301    } else if (mRepeatBufferDeferred) {
302        bool success = repeatLatestSubmittedBuffer_l();
303        if (success) {
304            ALOGV("deferred repeatLatestSubmittedBuffer_l SUCCESS");
305        } else {
306            ALOGV("deferred repeatLatestSubmittedBuffer_l FAILURE");
307        }
308        mRepeatBufferDeferred = false;
309    }
310
311    return;
312}
313
314void GraphicBufferSource::codecBufferFilled(OMX_BUFFERHEADERTYPE* header) {
315    Mutex::Autolock autoLock(mMutex);
316
317    if (mMaxTimestampGapUs > 0ll
318            && !(header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
319        ssize_t index = mOriginalTimeUs.indexOfKey(header->nTimeStamp);
320        if (index >= 0) {
321            ALOGV("OUT timestamp: %lld -> %lld",
322                    static_cast<long long>(header->nTimeStamp),
323                    static_cast<long long>(mOriginalTimeUs[index]));
324            header->nTimeStamp = mOriginalTimeUs[index];
325            mOriginalTimeUs.removeItemsAt(index);
326        } else {
327            // giving up the effort as encoder doesn't appear to preserve pts
328            ALOGW("giving up limiting timestamp gap (pts = %lld)",
329                    header->nTimeStamp);
330            mMaxTimestampGapUs = -1ll;
331        }
332        if (mOriginalTimeUs.size() > BufferQueue::NUM_BUFFER_SLOTS) {
333            // something terribly wrong must have happened, giving up...
334            ALOGE("mOriginalTimeUs has too many entries (%zu)",
335                    mOriginalTimeUs.size());
336            mMaxTimestampGapUs = -1ll;
337        }
338    }
339}
340
341void GraphicBufferSource::suspend(bool suspend) {
342    Mutex::Autolock autoLock(mMutex);
343
344    if (suspend) {
345        mSuspended = true;
346
347        while (mNumFramesAvailable > 0) {
348            BufferQueue::BufferItem item;
349            status_t err = mConsumer->acquireBuffer(&item, 0);
350
351            if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
352                // shouldn't happen.
353                ALOGW("suspend: frame was not available");
354                break;
355            } else if (err != OK) {
356                ALOGW("suspend: acquireBuffer returned err=%d", err);
357                break;
358            }
359
360            --mNumFramesAvailable;
361
362            mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
363                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
364        }
365        return;
366    }
367
368    mSuspended = false;
369
370    if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
371        if (repeatLatestSubmittedBuffer_l()) {
372            ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l SUCCESS");
373
374            mRepeatBufferDeferred = false;
375        } else {
376            ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l FAILURE");
377        }
378    }
379}
380
381bool GraphicBufferSource::fillCodecBuffer_l() {
382    CHECK(mExecuting && mNumFramesAvailable > 0);
383
384    if (mSuspended) {
385        return false;
386    }
387
388    int cbi = findAvailableCodecBuffer_l();
389    if (cbi < 0) {
390        // No buffers available, bail.
391        ALOGV("fillCodecBuffer_l: no codec buffers, avail now %zu",
392                mNumFramesAvailable);
393        return false;
394    }
395
396    ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
397            mNumFramesAvailable);
398    BufferQueue::BufferItem item;
399    status_t err = mConsumer->acquireBuffer(&item, 0);
400    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
401        // shouldn't happen
402        ALOGW("fillCodecBuffer_l: frame was not available");
403        return false;
404    } else if (err != OK) {
405        // now what? fake end-of-stream?
406        ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
407        return false;
408    }
409
410    mNumFramesAvailable--;
411
412    // Wait for it to become available.
413    err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l");
414    if (err != OK) {
415        ALOGW("failed to wait for buffer fence: %d", err);
416        // keep going
417    }
418
419    // If this is the first time we're seeing this buffer, add it to our
420    // slot table.
421    if (item.mGraphicBuffer != NULL) {
422        ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf);
423        mBufferSlot[item.mBuf] = item.mGraphicBuffer;
424    }
425
426    err = UNKNOWN_ERROR;
427
428    // only submit sample if start time is unspecified, or sample
429    // is queued after the specified start time
430    if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) {
431        // if start time is set, offset time stamp by start time
432        if (mSkipFramesBeforeNs > 0) {
433            item.mTimestamp -= mSkipFramesBeforeNs;
434        }
435        err = submitBuffer_l(item, cbi);
436    }
437
438    if (err != OK) {
439        ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf);
440        mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
441                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
442    } else {
443        ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi);
444        setLatestSubmittedBuffer_l(item);
445    }
446
447    return true;
448}
449
450bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() {
451    CHECK(mExecuting && mNumFramesAvailable == 0);
452
453    if (mLatestSubmittedBufferId < 0 || mSuspended) {
454        return false;
455    }
456    if (mBufferSlot[mLatestSubmittedBufferId] == NULL) {
457        // This can happen if the remote side disconnects, causing
458        // onBuffersReleased() to NULL out our copy of the slots.  The
459        // buffer is gone, so we have nothing to show.
460        //
461        // To be on the safe side we try to release the buffer.
462        ALOGD("repeatLatestSubmittedBuffer_l: slot was NULL");
463        mConsumer->releaseBuffer(
464                mLatestSubmittedBufferId,
465                mLatestSubmittedBufferFrameNum,
466                EGL_NO_DISPLAY,
467                EGL_NO_SYNC_KHR,
468                Fence::NO_FENCE);
469        mLatestSubmittedBufferId = -1;
470        mLatestSubmittedBufferFrameNum = 0;
471        return false;
472    }
473
474    int cbi = findAvailableCodecBuffer_l();
475    if (cbi < 0) {
476        // No buffers available, bail.
477        ALOGV("repeatLatestSubmittedBuffer_l: no codec buffers.");
478        return false;
479    }
480
481    BufferQueue::BufferItem item;
482    item.mBuf = mLatestSubmittedBufferId;
483    item.mFrameNumber = mLatestSubmittedBufferFrameNum;
484    item.mTimestamp = mRepeatLastFrameTimestamp;
485
486    status_t err = submitBuffer_l(item, cbi);
487
488    if (err != OK) {
489        return false;
490    }
491
492    ++mLatestSubmittedBufferUseCount;
493
494    /* repeat last frame up to kRepeatLastFrameCount times.
495     * in case of static scene, a single repeat might not get rid of encoder
496     * ghosting completely, refresh a couple more times to get better quality
497     */
498    if (--mRepeatLastFrameCount > 0) {
499        mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
500
501        if (mReflector != NULL) {
502            sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id());
503            msg->setInt32("generation", ++mRepeatLastFrameGeneration);
504            msg->post(mRepeatAfterUs);
505        }
506    }
507
508    return true;
509}
510
511void GraphicBufferSource::setLatestSubmittedBuffer_l(
512        const BufferQueue::BufferItem &item) {
513    ALOGV("setLatestSubmittedBuffer_l");
514
515    if (mLatestSubmittedBufferId >= 0) {
516        if (mLatestSubmittedBufferUseCount == 0) {
517            mConsumer->releaseBuffer(
518                    mLatestSubmittedBufferId,
519                    mLatestSubmittedBufferFrameNum,
520                    EGL_NO_DISPLAY,
521                    EGL_NO_SYNC_KHR,
522                    Fence::NO_FENCE);
523        }
524    }
525
526    mLatestSubmittedBufferId = item.mBuf;
527    mLatestSubmittedBufferFrameNum = item.mFrameNumber;
528    mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
529
530    mLatestSubmittedBufferUseCount = 1;
531    mRepeatBufferDeferred = false;
532    mRepeatLastFrameCount = kRepeatLastFrameCount;
533
534    if (mReflector != NULL) {
535        sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id());
536        msg->setInt32("generation", ++mRepeatLastFrameGeneration);
537        msg->post(mRepeatAfterUs);
538    }
539}
540
541status_t GraphicBufferSource::signalEndOfInputStream() {
542    Mutex::Autolock autoLock(mMutex);
543    ALOGV("signalEndOfInputStream: exec=%d avail=%zu eos=%d",
544            mExecuting, mNumFramesAvailable, mEndOfStream);
545
546    if (mEndOfStream) {
547        ALOGE("EOS was already signaled");
548        return INVALID_OPERATION;
549    }
550
551    // Set the end-of-stream flag.  If no frames are pending from the
552    // BufferQueue, and a codec buffer is available, and we're executing,
553    // we initiate the EOS from here.  Otherwise, we'll let
554    // codecBufferEmptied() (or omxExecuting) do it.
555    //
556    // Note: if there are no pending frames and all codec buffers are
557    // available, we *must* submit the EOS from here or we'll just
558    // stall since no future events are expected.
559    mEndOfStream = true;
560
561    if (mExecuting && mNumFramesAvailable == 0) {
562        submitEndOfInputStream_l();
563    }
564
565    return OK;
566}
567
568int64_t GraphicBufferSource::getTimestamp(const BufferQueue::BufferItem &item) {
569    int64_t timeUs = item.mTimestamp / 1000;
570
571    if (mTimePerCaptureUs > 0ll) {
572        // Time lapse or slow motion mode
573        if (mPrevCaptureUs < 0ll) {
574            // first capture
575            mPrevCaptureUs = timeUs;
576            mPrevFrameUs = timeUs;
577        } else {
578            // snap to nearest capture point
579            int64_t nFrames = (timeUs + mTimePerCaptureUs / 2 - mPrevCaptureUs)
580                    / mTimePerCaptureUs;
581            if (nFrames <= 0) {
582                // skip this frame as it's too close to previous capture
583                ALOGV("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
584                return -1;
585            }
586            mPrevCaptureUs = mPrevCaptureUs + nFrames * mTimePerCaptureUs;
587            mPrevFrameUs += mTimePerFrameUs * nFrames;
588        }
589
590        ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
591                static_cast<long long>(timeUs),
592                static_cast<long long>(mPrevCaptureUs),
593                static_cast<long long>(mPrevFrameUs));
594
595        return mPrevFrameUs;
596    } else if (mMaxTimestampGapUs > 0ll) {
597        /* Cap timestamp gap between adjacent frames to specified max
598         *
599         * In the scenario of cast mirroring, encoding could be suspended for
600         * prolonged periods. Limiting the pts gap to workaround the problem
601         * where encoder's rate control logic produces huge frames after a
602         * long period of suspension.
603         */
604
605        int64_t originalTimeUs = timeUs;
606        if (mPrevOriginalTimeUs >= 0ll) {
607            if (originalTimeUs < mPrevOriginalTimeUs) {
608                // Drop the frame if it's going backward in time. Bad timestamp
609                // could disrupt encoder's rate control completely.
610                ALOGW("Dropping frame that's going backward in time");
611                return -1;
612            }
613            int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
614            timeUs = (timestampGapUs < mMaxTimestampGapUs ?
615                    timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
616        }
617        mPrevOriginalTimeUs = originalTimeUs;
618        mPrevModifiedTimeUs = timeUs;
619        mOriginalTimeUs.add(timeUs, originalTimeUs);
620        ALOGV("IN  timestamp: %lld -> %lld",
621            static_cast<long long>(originalTimeUs),
622            static_cast<long long>(timeUs));
623    }
624
625    return timeUs;
626}
627
628status_t GraphicBufferSource::submitBuffer_l(
629        const BufferQueue::BufferItem &item, int cbi) {
630    ALOGV("submitBuffer_l cbi=%d", cbi);
631
632    int64_t timeUs = getTimestamp(item);
633    if (timeUs < 0ll) {
634        return UNKNOWN_ERROR;
635    }
636
637    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
638    codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf];
639    codecBuffer.mBuf = item.mBuf;
640    codecBuffer.mFrameNumber = item.mFrameNumber;
641
642    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
643    CHECK(header->nAllocLen >= 4 + sizeof(buffer_handle_t));
644    OMX_U8* data = header->pBuffer;
645    const OMX_U32 type = kMetadataBufferTypeGrallocSource;
646    buffer_handle_t handle = codecBuffer.mGraphicBuffer->handle;
647    memcpy(data, &type, 4);
648    memcpy(data + 4, &handle, sizeof(buffer_handle_t));
649
650    status_t err = mNodeInstance->emptyDirectBuffer(header, 0,
651            4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME,
652            timeUs);
653    if (err != OK) {
654        ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err);
655        codecBuffer.mGraphicBuffer = NULL;
656        return err;
657    }
658
659    ALOGV("emptyDirectBuffer succeeded, h=%p p=%p bufhandle=%p",
660            header, header->pBuffer, handle);
661    return OK;
662}
663
664void GraphicBufferSource::submitEndOfInputStream_l() {
665    CHECK(mEndOfStream);
666    if (mEndOfStreamSent) {
667        ALOGV("EOS already sent");
668        return;
669    }
670
671    int cbi = findAvailableCodecBuffer_l();
672    if (cbi < 0) {
673        ALOGV("submitEndOfInputStream_l: no codec buffers available");
674        return;
675    }
676
677    // We reject any additional incoming graphic buffers, so there's no need
678    // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as
679    // in-use.
680    CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
681
682    OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
683    if (EXTRA_CHECK) {
684        // Guard against implementations that don't check nFilledLen.
685        size_t fillLen = 4 + sizeof(buffer_handle_t);
686        CHECK(header->nAllocLen >= fillLen);
687        OMX_U8* data = header->pBuffer;
688        memset(data, 0xcd, fillLen);
689    }
690
691    uint64_t timestamp = 0; // does this matter?
692
693    status_t err = mNodeInstance->emptyDirectBuffer(header, /*offset*/ 0,
694            /*length*/ 0, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
695            timestamp);
696    if (err != OK) {
697        ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
698    } else {
699        ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d",
700                header, cbi);
701        mEndOfStreamSent = true;
702    }
703}
704
705int GraphicBufferSource::findAvailableCodecBuffer_l() {
706    CHECK(mCodecBuffers.size() > 0);
707
708    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
709        if (mCodecBuffers[i].mGraphicBuffer == NULL) {
710            return i;
711        }
712    }
713    return -1;
714}
715
716int GraphicBufferSource::findMatchingCodecBuffer_l(
717        const OMX_BUFFERHEADERTYPE* header) {
718    for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
719        if (mCodecBuffers[i].mHeader == header) {
720            return i;
721        }
722    }
723    return -1;
724}
725
726// BufferQueue::ConsumerListener callback
727void GraphicBufferSource::onFrameAvailable() {
728    Mutex::Autolock autoLock(mMutex);
729
730    ALOGV("onFrameAvailable exec=%d avail=%zu",
731            mExecuting, mNumFramesAvailable);
732
733    if (mEndOfStream || mSuspended) {
734        if (mEndOfStream) {
735            // This should only be possible if a new buffer was queued after
736            // EOS was signaled, i.e. the app is misbehaving.
737
738            ALOGW("onFrameAvailable: EOS is set, ignoring frame");
739        } else {
740            ALOGV("onFrameAvailable: suspended, ignoring frame");
741        }
742
743        BufferQueue::BufferItem item;
744        status_t err = mConsumer->acquireBuffer(&item, 0);
745        if (err == OK) {
746            // If this is the first time we're seeing this buffer, add it to our
747            // slot table.
748            if (item.mGraphicBuffer != NULL) {
749                ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mBuf);
750                mBufferSlot[item.mBuf] = item.mGraphicBuffer;
751            }
752            mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
753                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
754        }
755        return;
756    }
757
758    mNumFramesAvailable++;
759
760    mRepeatBufferDeferred = false;
761    ++mRepeatLastFrameGeneration;
762
763    if (mExecuting) {
764        fillCodecBuffer_l();
765    }
766}
767
768// BufferQueue::ConsumerListener callback
769void GraphicBufferSource::onBuffersReleased() {
770    Mutex::Autolock lock(mMutex);
771
772    uint64_t slotMask;
773    if (mConsumer->getReleasedBuffers(&slotMask) != NO_ERROR) {
774        ALOGW("onBuffersReleased: unable to get released buffer set");
775        slotMask = 0xffffffffffffffffULL;
776    }
777
778    ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
779
780    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
781        if ((slotMask & 0x01) != 0) {
782            mBufferSlot[i] = NULL;
783        }
784        slotMask >>= 1;
785    }
786}
787
788// BufferQueue::ConsumerListener callback
789void GraphicBufferSource::onSidebandStreamChanged() {
790    ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
791}
792
793status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(
794        int64_t repeatAfterUs) {
795    Mutex::Autolock autoLock(mMutex);
796
797    if (mExecuting || repeatAfterUs <= 0ll) {
798        return INVALID_OPERATION;
799    }
800
801    mRepeatAfterUs = repeatAfterUs;
802
803    return OK;
804}
805
806status_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) {
807    Mutex::Autolock autoLock(mMutex);
808
809    if (mExecuting || maxGapUs <= 0ll) {
810        return INVALID_OPERATION;
811    }
812
813    mMaxTimestampGapUs = maxGapUs;
814
815    return OK;
816}
817
818void GraphicBufferSource::setSkipFramesBeforeUs(int64_t skipFramesBeforeUs) {
819    Mutex::Autolock autoLock(mMutex);
820
821    mSkipFramesBeforeNs =
822            (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll;
823}
824
825status_t GraphicBufferSource::setTimeLapseUs(int64_t* data) {
826    Mutex::Autolock autoLock(mMutex);
827
828    if (mExecuting || data[0] <= 0ll || data[1] <= 0ll) {
829        return INVALID_OPERATION;
830    }
831
832    mTimePerFrameUs = data[0];
833    mTimePerCaptureUs = data[1];
834
835    return OK;
836}
837
838void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
839    switch (msg->what()) {
840        case kWhatRepeatLastFrame:
841        {
842            Mutex::Autolock autoLock(mMutex);
843
844            int32_t generation;
845            CHECK(msg->findInt32("generation", &generation));
846
847            if (generation != mRepeatLastFrameGeneration) {
848                // stale
849                break;
850            }
851
852            if (!mExecuting || mNumFramesAvailable > 0) {
853                break;
854            }
855
856            bool success = repeatLatestSubmittedBuffer_l();
857
858            if (success) {
859                ALOGV("repeatLatestSubmittedBuffer_l SUCCESS");
860            } else {
861                ALOGV("repeatLatestSubmittedBuffer_l FAILURE");
862                mRepeatBufferDeferred = true;
863            }
864            break;
865        }
866
867        default:
868            TRESPASS();
869    }
870}
871
872}  // namespace android
873