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