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