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