• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h
24 
25 #include "GraphicBufferSource.h"
26 #include "OMXUtils.h"
27 
28 #include <OMX_Core.h>
29 #include <OMX_IndexExt.h>
30 #include <media/stagefright/foundation/ADebug.h>
31 #include <media/stagefright/foundation/AMessage.h>
32 #include <media/stagefright/foundation/ColorUtils.h>
33 
34 #include <media/hardware/MetadataBufferType.h>
35 #include <ui/GraphicBuffer.h>
36 #include <gui/BufferItem.h>
37 #include <HardwareAPI.h>
38 
39 #include <inttypes.h>
40 #include "FrameDropper.h"
41 
42 namespace android {
43 
44 static const bool EXTRA_CHECK = true;
45 
46 static const OMX_U32 kPortIndexInput = 0;
47 
PersistentProxyListener(const wp<IGraphicBufferConsumer> & consumer,const wp<ConsumerListener> & consumerListener)48 GraphicBufferSource::PersistentProxyListener::PersistentProxyListener(
49         const wp<IGraphicBufferConsumer> &consumer,
50         const wp<ConsumerListener>& consumerListener) :
51     mConsumerListener(consumerListener),
52     mConsumer(consumer) {}
53 
~PersistentProxyListener()54 GraphicBufferSource::PersistentProxyListener::~PersistentProxyListener() {}
55 
onFrameAvailable(const BufferItem & item)56 void GraphicBufferSource::PersistentProxyListener::onFrameAvailable(
57         const BufferItem& item) {
58     sp<ConsumerListener> listener(mConsumerListener.promote());
59     if (listener != NULL) {
60         listener->onFrameAvailable(item);
61     } else {
62         sp<IGraphicBufferConsumer> consumer(mConsumer.promote());
63         if (consumer == NULL) {
64             return;
65         }
66         BufferItem bi;
67         status_t err = consumer->acquireBuffer(&bi, 0);
68         if (err != OK) {
69             ALOGE("PersistentProxyListener: acquireBuffer failed (%d)", err);
70             return;
71         }
72 
73         err = consumer->detachBuffer(bi.mSlot);
74         if (err != OK) {
75             ALOGE("PersistentProxyListener: detachBuffer failed (%d)", err);
76             return;
77         }
78 
79         err = consumer->attachBuffer(&bi.mSlot, bi.mGraphicBuffer);
80         if (err != OK) {
81             ALOGE("PersistentProxyListener: attachBuffer failed (%d)", err);
82             return;
83         }
84 
85         err = consumer->releaseBuffer(bi.mSlot, 0,
86                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, bi.mFence);
87         if (err != OK) {
88             ALOGE("PersistentProxyListener: releaseBuffer failed (%d)", err);
89         }
90     }
91 }
92 
onFrameReplaced(const BufferItem & item)93 void GraphicBufferSource::PersistentProxyListener::onFrameReplaced(
94         const BufferItem& item) {
95     sp<ConsumerListener> listener(mConsumerListener.promote());
96     if (listener != NULL) {
97         listener->onFrameReplaced(item);
98     }
99 }
100 
onBuffersReleased()101 void GraphicBufferSource::PersistentProxyListener::onBuffersReleased() {
102     sp<ConsumerListener> listener(mConsumerListener.promote());
103     if (listener != NULL) {
104         listener->onBuffersReleased();
105     }
106 }
107 
onSidebandStreamChanged()108 void GraphicBufferSource::PersistentProxyListener::onSidebandStreamChanged() {
109     sp<ConsumerListener> listener(mConsumerListener.promote());
110     if (listener != NULL) {
111         listener->onSidebandStreamChanged();
112     }
113 }
114 
GraphicBufferSource(OMXNodeInstance * nodeInstance,uint32_t bufferWidth,uint32_t bufferHeight,uint32_t bufferCount,uint32_t consumerUsage,const sp<IGraphicBufferConsumer> & consumer)115 GraphicBufferSource::GraphicBufferSource(
116         OMXNodeInstance* nodeInstance,
117         uint32_t bufferWidth,
118         uint32_t bufferHeight,
119         uint32_t bufferCount,
120         uint32_t consumerUsage,
121         const sp<IGraphicBufferConsumer> &consumer) :
122     mInitCheck(UNKNOWN_ERROR),
123     mNodeInstance(nodeInstance),
124     mExecuting(false),
125     mSuspended(false),
126     mLastDataSpace(HAL_DATASPACE_UNKNOWN),
127     mIsPersistent(false),
128     mConsumer(consumer),
129     mNumFramesAvailable(0),
130     mNumBufferAcquired(0),
131     mEndOfStream(false),
132     mEndOfStreamSent(false),
133     mMaxTimestampGapUs(-1ll),
134     mPrevOriginalTimeUs(-1ll),
135     mPrevModifiedTimeUs(-1ll),
136     mSkipFramesBeforeNs(-1ll),
137     mRepeatAfterUs(-1ll),
138     mRepeatLastFrameGeneration(0),
139     mRepeatLastFrameTimestamp(-1ll),
140     mLatestBufferId(-1),
141     mLatestBufferFrameNum(0),
142     mLatestBufferUseCount(0),
143     mLatestBufferFence(Fence::NO_FENCE),
144     mRepeatBufferDeferred(false),
145     mTimePerCaptureUs(-1ll),
146     mTimePerFrameUs(-1ll),
147     mPrevCaptureUs(-1ll),
148     mPrevFrameUs(-1ll),
149     mInputBufferTimeOffsetUs(0ll) {
150 
151     ALOGV("GraphicBufferSource w=%u h=%u c=%u",
152             bufferWidth, bufferHeight, bufferCount);
153 
154     if (bufferWidth == 0 || bufferHeight == 0) {
155         ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
156         mInitCheck = BAD_VALUE;
157         return;
158     }
159 
160     if (mConsumer == NULL) {
161         String8 name("GraphicBufferSource");
162 
163         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
164         mConsumer->setConsumerName(name);
165 
166         // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER
167         // for backward compatibility.
168         consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
169         mConsumer->setConsumerUsageBits(consumerUsage);
170 
171         mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
172         if (mInitCheck != NO_ERROR) {
173             ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
174                     bufferCount, mInitCheck);
175             return;
176         }
177     } else {
178         mIsPersistent = true;
179     }
180     mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
181     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
182     // reference once the ctor ends, as that would cause the refcount of 'this'
183     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
184     // that's what we create.
185     wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
186     sp<IConsumerListener> proxy;
187     if (!mIsPersistent) {
188         proxy = new BufferQueue::ProxyConsumerListener(listener);
189     } else {
190         proxy = new PersistentProxyListener(mConsumer, listener);
191     }
192 
193     mInitCheck = mConsumer->consumerConnect(proxy, false);
194     if (mInitCheck != NO_ERROR) {
195         ALOGE("Error connecting to BufferQueue: %s (%d)",
196                 strerror(-mInitCheck), mInitCheck);
197         return;
198     }
199 
200     memset(&mColorAspects, 0, sizeof(mColorAspects));
201 
202     CHECK(mInitCheck == NO_ERROR);
203 }
204 
~GraphicBufferSource()205 GraphicBufferSource::~GraphicBufferSource() {
206     if (mLatestBufferId >= 0) {
207         releaseBuffer(
208                 mLatestBufferId, mLatestBufferFrameNum,
209                 mBufferSlot[mLatestBufferId], mLatestBufferFence);
210     }
211     if (mNumBufferAcquired != 0) {
212         ALOGW("potential buffer leak (acquired %d)", mNumBufferAcquired);
213     }
214     if (mConsumer != NULL && !mIsPersistent) {
215         status_t err = mConsumer->consumerDisconnect();
216         if (err != NO_ERROR) {
217             ALOGW("consumerDisconnect failed: %d", err);
218         }
219     }
220 }
221 
omxExecuting()222 void GraphicBufferSource::omxExecuting() {
223     Mutex::Autolock autoLock(mMutex);
224     ALOGV("--> executing; avail=%zu, codec vec size=%zd",
225             mNumFramesAvailable, mCodecBuffers.size());
226     CHECK(!mExecuting);
227     mExecuting = true;
228     mLastDataSpace = HAL_DATASPACE_UNKNOWN;
229     ALOGV("clearing last dataSpace");
230 
231     // Start by loading up as many buffers as possible.  We want to do this,
232     // rather than just submit the first buffer, to avoid a degenerate case:
233     // if all BQ buffers arrive before we start executing, and we only submit
234     // one here, the other BQ buffers will just sit until we get notified
235     // that the codec buffer has been released.  We'd then acquire and
236     // submit a single additional buffer, repeatedly, never using more than
237     // one codec buffer simultaneously.  (We could instead try to submit
238     // all BQ buffers whenever any codec buffer is freed, but if we get the
239     // initial conditions right that will never be useful.)
240     while (mNumFramesAvailable) {
241         if (!fillCodecBuffer_l()) {
242             ALOGV("stop load with frames available (codecAvail=%d)",
243                     isCodecBufferAvailable_l());
244             break;
245         }
246     }
247 
248     ALOGV("done loading initial frames, avail=%zu", mNumFramesAvailable);
249 
250     // If EOS has already been signaled, and there are no more frames to
251     // submit, try to send EOS now as well.
252     if (mEndOfStream && mNumFramesAvailable == 0) {
253         submitEndOfInputStream_l();
254     }
255 
256     if (mRepeatAfterUs > 0ll && mLooper == NULL) {
257         mReflector = new AHandlerReflector<GraphicBufferSource>(this);
258 
259         mLooper = new ALooper;
260         mLooper->registerHandler(mReflector);
261         mLooper->start();
262 
263         if (mLatestBufferId >= 0) {
264             sp<AMessage> msg =
265                 new AMessage(kWhatRepeatLastFrame, mReflector);
266 
267             msg->setInt32("generation", ++mRepeatLastFrameGeneration);
268             msg->post(mRepeatAfterUs);
269         }
270     }
271 }
272 
omxIdle()273 void GraphicBufferSource::omxIdle() {
274     ALOGV("omxIdle");
275 
276     Mutex::Autolock autoLock(mMutex);
277 
278     if (mExecuting) {
279         // We are only interested in the transition from executing->idle,
280         // not loaded->idle.
281         mExecuting = false;
282     }
283 }
284 
omxLoaded()285 void GraphicBufferSource::omxLoaded(){
286     Mutex::Autolock autoLock(mMutex);
287     if (!mExecuting) {
288         // This can happen if something failed very early.
289         ALOGW("Dropped back down to Loaded without Executing");
290     }
291 
292     if (mLooper != NULL) {
293         mLooper->unregisterHandler(mReflector->id());
294         mReflector.clear();
295 
296         mLooper->stop();
297         mLooper.clear();
298     }
299 
300     ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d",
301             mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
302 
303     // Codec is no longer executing.  Discard all codec-related state.
304     mCodecBuffers.clear();
305     // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
306     //       are null; complain if not
307 
308     mExecuting = false;
309 }
310 
addCodecBuffer(OMX_BUFFERHEADERTYPE * header)311 void GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) {
312     Mutex::Autolock autoLock(mMutex);
313 
314     if (mExecuting) {
315         // This should never happen -- buffers can only be allocated when
316         // transitioning from "loaded" to "idle".
317         ALOGE("addCodecBuffer: buffer added while executing");
318         return;
319     }
320 
321     ALOGV("addCodecBuffer h=%p size=%" PRIu32 " p=%p",
322             header, header->nAllocLen, header->pBuffer);
323     CodecBuffer codecBuffer;
324     codecBuffer.mHeader = header;
325     mCodecBuffers.add(codecBuffer);
326 }
327 
codecBufferEmptied(OMX_BUFFERHEADERTYPE * header,int fenceFd)328 void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header, int fenceFd) {
329     Mutex::Autolock autoLock(mMutex);
330     if (!mExecuting) {
331         return;
332     }
333 
334     int cbi = findMatchingCodecBuffer_l(header);
335     if (cbi < 0) {
336         // This should never happen.
337         ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header);
338         if (fenceFd >= 0) {
339             ::close(fenceFd);
340         }
341         return;
342     }
343 
344     ALOGV("codecBufferEmptied h=%p size=%" PRIu32 " filled=%" PRIu32 " p=%p",
345             header, header->nAllocLen, header->nFilledLen,
346             header->pBuffer);
347     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
348 
349     // header->nFilledLen may not be the original value, so we can't compare
350     // that to zero to see of this was the EOS buffer.  Instead we just
351     // see if the GraphicBuffer reference was null, which should only ever
352     // happen for EOS.
353     if (codecBuffer.mGraphicBuffer == NULL) {
354         if (!(mEndOfStream && mEndOfStreamSent)) {
355             // This can happen when broken code sends us the same buffer
356             // twice in a row.
357             ALOGE("ERROR: codecBufferEmptied on non-EOS null buffer "
358                     "(buffer emptied twice?)");
359         }
360         // No GraphicBuffer to deal with, no additional input or output is
361         // expected, so just return.
362         if (fenceFd >= 0) {
363             ::close(fenceFd);
364         }
365         return;
366     }
367 
368     if (EXTRA_CHECK && header->nAllocLen >= sizeof(MetadataBufferType)) {
369         // Pull the graphic buffer handle back out of the buffer, and confirm
370         // that it matches expectations.
371         OMX_U8* data = header->pBuffer;
372         MetadataBufferType type = *(MetadataBufferType *)data;
373         if (type == kMetadataBufferTypeGrallocSource
374                 && header->nAllocLen >= sizeof(VideoGrallocMetadata)) {
375             VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)data;
376             if (grallocMeta.pHandle != codecBuffer.mGraphicBuffer->handle) {
377                 // should never happen
378                 ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
379                         grallocMeta.pHandle, codecBuffer.mGraphicBuffer->handle);
380                 CHECK(!"codecBufferEmptied: mismatched buffer");
381             }
382         } else if (type == kMetadataBufferTypeANWBuffer
383                 && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
384             VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)data;
385             if (nativeMeta.pBuffer != codecBuffer.mGraphicBuffer->getNativeBuffer()) {
386                 // should never happen
387                 ALOGE("codecBufferEmptied: buffer is %p, expected %p",
388                         nativeMeta.pBuffer, codecBuffer.mGraphicBuffer->getNativeBuffer());
389                 CHECK(!"codecBufferEmptied: mismatched buffer");
390             }
391         }
392     }
393 
394     // Find matching entry in our cached copy of the BufferQueue slots.
395     // If we find a match, release that slot.  If we don't, the BufferQueue
396     // has dropped that GraphicBuffer, and there's nothing for us to release.
397     int id = codecBuffer.mSlot;
398     sp<Fence> fence = new Fence(fenceFd);
399     if (mBufferSlot[id] != NULL &&
400         mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
401         ALOGV("cbi %d matches bq slot %d, handle=%p",
402                 cbi, id, mBufferSlot[id]->handle);
403 
404         if (id == mLatestBufferId) {
405             CHECK_GT(mLatestBufferUseCount--, 0);
406         } else {
407             releaseBuffer(id, codecBuffer.mFrameNumber, mBufferSlot[id], fence);
408         }
409     } else {
410         ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
411                 cbi);
412         // we will not reuse codec buffer, so there is no need to wait for fence
413     }
414 
415     // Mark the codec buffer as available by clearing the GraphicBuffer ref.
416     codecBuffer.mGraphicBuffer = NULL;
417 
418     if (mNumFramesAvailable) {
419         // Fill this codec buffer.
420         CHECK(!mEndOfStreamSent);
421         ALOGV("buffer freed, %zu frames avail (eos=%d)",
422                 mNumFramesAvailable, mEndOfStream);
423         fillCodecBuffer_l();
424     } else if (mEndOfStream) {
425         // No frames available, but EOS is pending, so use this buffer to
426         // send that.
427         ALOGV("buffer freed, EOS pending");
428         submitEndOfInputStream_l();
429     } else if (mRepeatBufferDeferred) {
430         bool success = repeatLatestBuffer_l();
431         if (success) {
432             ALOGV("deferred repeatLatestBuffer_l SUCCESS");
433         } else {
434             ALOGV("deferred repeatLatestBuffer_l FAILURE");
435         }
436         mRepeatBufferDeferred = false;
437     }
438 
439     return;
440 }
441 
codecBufferFilled(OMX_BUFFERHEADERTYPE * header)442 void GraphicBufferSource::codecBufferFilled(OMX_BUFFERHEADERTYPE* header) {
443     Mutex::Autolock autoLock(mMutex);
444 
445     if (mMaxTimestampGapUs > 0ll
446             && !(header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
447         ssize_t index = mOriginalTimeUs.indexOfKey(header->nTimeStamp);
448         if (index >= 0) {
449             ALOGV("OUT timestamp: %lld -> %lld",
450                     static_cast<long long>(header->nTimeStamp),
451                     static_cast<long long>(mOriginalTimeUs[index]));
452             header->nTimeStamp = mOriginalTimeUs[index];
453             mOriginalTimeUs.removeItemsAt(index);
454         } else {
455             // giving up the effort as encoder doesn't appear to preserve pts
456             ALOGW("giving up limiting timestamp gap (pts = %lld)",
457                     header->nTimeStamp);
458             mMaxTimestampGapUs = -1ll;
459         }
460         if (mOriginalTimeUs.size() > BufferQueue::NUM_BUFFER_SLOTS) {
461             // something terribly wrong must have happened, giving up...
462             ALOGE("mOriginalTimeUs has too many entries (%zu)",
463                     mOriginalTimeUs.size());
464             mMaxTimestampGapUs = -1ll;
465         }
466     }
467 }
468 
suspend(bool suspend)469 void GraphicBufferSource::suspend(bool suspend) {
470     Mutex::Autolock autoLock(mMutex);
471 
472     if (suspend) {
473         mSuspended = true;
474 
475         while (mNumFramesAvailable > 0) {
476             BufferItem item;
477             status_t err = mConsumer->acquireBuffer(&item, 0);
478 
479             if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
480                 // shouldn't happen.
481                 ALOGW("suspend: frame was not available");
482                 break;
483             } else if (err != OK) {
484                 ALOGW("suspend: acquireBuffer returned err=%d", err);
485                 break;
486             }
487 
488             ++mNumBufferAcquired;
489             --mNumFramesAvailable;
490 
491             releaseBuffer(item.mSlot, item.mFrameNumber,
492                     item.mGraphicBuffer, item.mFence);
493         }
494         return;
495     }
496 
497     mSuspended = false;
498 
499     if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
500         if (repeatLatestBuffer_l()) {
501             ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
502 
503             mRepeatBufferDeferred = false;
504         } else {
505             ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
506         }
507     }
508 }
509 
onDataSpaceChanged_l(android_dataspace dataSpace,android_pixel_format pixelFormat)510 void GraphicBufferSource::onDataSpaceChanged_l(
511         android_dataspace dataSpace, android_pixel_format pixelFormat) {
512     ALOGD("got buffer with new dataSpace #%x", dataSpace);
513     mLastDataSpace = dataSpace;
514 
515     if (ColorUtils::convertDataSpaceToV0(dataSpace)) {
516         ColorAspects aspects = mColorAspects; // initially requested aspects
517 
518         // request color aspects to encode
519         OMX_INDEXTYPE index;
520         status_t err = mNodeInstance->getExtensionIndex(
521                 "OMX.google.android.index.describeColorAspects", &index);
522         if (err == OK) {
523             // V0 dataspace
524             DescribeColorAspectsParams params;
525             InitOMXParams(&params);
526             params.nPortIndex = kPortIndexInput;
527             params.nDataSpace = mLastDataSpace;
528             params.nPixelFormat = pixelFormat;
529             params.bDataSpaceChanged = OMX_TRUE;
530             params.sAspects = mColorAspects;
531 
532             err = mNodeInstance->getConfig(index, &params, sizeof(params));
533             if (err == OK) {
534                 aspects = params.sAspects;
535                 ALOGD("Codec resolved it to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
536                         params.sAspects.mRange, asString(params.sAspects.mRange),
537                         params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
538                         params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
539                         params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
540                         err, asString(err));
541             } else {
542                 params.sAspects = aspects;
543                 err = OK;
544             }
545             params.bDataSpaceChanged = OMX_FALSE;
546             for (int triesLeft = 2; --triesLeft >= 0; ) {
547                 status_t err = mNodeInstance->setConfig(index, &params, sizeof(params));
548                 if (err == OK) {
549                     err = mNodeInstance->getConfig(index, &params, sizeof(params));
550                 }
551                 if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
552                         params.sAspects, aspects)) {
553                     // if we can't set or get color aspects, still communicate dataspace to client
554                     break;
555                 }
556 
557                 ALOGW_IF(triesLeft == 0, "Codec repeatedly changed requested ColorAspects.");
558             }
559         }
560 
561         ALOGV("Set color aspects to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
562                 aspects.mRange, asString(aspects.mRange),
563                 aspects.mPrimaries, asString(aspects.mPrimaries),
564                 aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
565                 aspects.mTransfer, asString(aspects.mTransfer),
566                 err, asString(err));
567 
568         // signal client that the dataspace has changed; this will update the output format
569         // TODO: we should tie this to an output buffer somehow, and signal the change
570         // just before the output buffer is returned to the client, but there are many
571         // ways this could fail (e.g. flushing), and we are not yet supporting this scenario.
572 
573         mNodeInstance->signalEvent(
574                 OMX_EventDataSpaceChanged, dataSpace,
575                 (aspects.mRange << 24) | (aspects.mPrimaries << 16)
576                         | (aspects.mMatrixCoeffs << 8) | aspects.mTransfer);
577     }
578 }
579 
fillCodecBuffer_l()580 bool GraphicBufferSource::fillCodecBuffer_l() {
581     CHECK(mExecuting && mNumFramesAvailable > 0);
582 
583     if (mSuspended) {
584         return false;
585     }
586 
587     int cbi = findAvailableCodecBuffer_l();
588     if (cbi < 0) {
589         // No buffers available, bail.
590         ALOGV("fillCodecBuffer_l: no codec buffers, avail now %zu",
591                 mNumFramesAvailable);
592         return false;
593     }
594 
595     ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
596             mNumFramesAvailable);
597     BufferItem item;
598     status_t err = mConsumer->acquireBuffer(&item, 0);
599     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
600         // shouldn't happen
601         ALOGW("fillCodecBuffer_l: frame was not available");
602         return false;
603     } else if (err != OK) {
604         // now what? fake end-of-stream?
605         ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
606         return false;
607     }
608 
609     mNumBufferAcquired++;
610     mNumFramesAvailable--;
611 
612     // If this is the first time we're seeing this buffer, add it to our
613     // slot table.
614     if (item.mGraphicBuffer != NULL) {
615         ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mSlot);
616         mBufferSlot[item.mSlot] = item.mGraphicBuffer;
617     }
618 
619     if (item.mDataSpace != mLastDataSpace) {
620         onDataSpaceChanged_l(
621                 item.mDataSpace, (android_pixel_format)mBufferSlot[item.mSlot]->getPixelFormat());
622     }
623 
624 
625     err = UNKNOWN_ERROR;
626 
627     // only submit sample if start time is unspecified, or sample
628     // is queued after the specified start time
629     bool dropped = false;
630     if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) {
631         // if start time is set, offset time stamp by start time
632         if (mSkipFramesBeforeNs > 0) {
633             item.mTimestamp -= mSkipFramesBeforeNs;
634         }
635 
636         int64_t timeUs = item.mTimestamp / 1000;
637         if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) {
638             ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs));
639             // set err to OK so that the skipped frame can still be saved as the lastest frame
640             err = OK;
641             dropped = true;
642         } else {
643             err = submitBuffer_l(item, cbi);
644         }
645     }
646 
647     if (err != OK) {
648         ALOGV("submitBuffer_l failed, releasing bq slot %d", item.mSlot);
649         releaseBuffer(item.mSlot, item.mFrameNumber, item.mGraphicBuffer, item.mFence);
650     } else {
651         ALOGV("buffer submitted (bq %d, cbi %d)", item.mSlot, cbi);
652         setLatestBuffer_l(item, dropped);
653     }
654 
655     return true;
656 }
657 
repeatLatestBuffer_l()658 bool GraphicBufferSource::repeatLatestBuffer_l() {
659     CHECK(mExecuting && mNumFramesAvailable == 0);
660 
661     if (mLatestBufferId < 0 || mSuspended) {
662         return false;
663     }
664     if (mBufferSlot[mLatestBufferId] == NULL) {
665         // This can happen if the remote side disconnects, causing
666         // onBuffersReleased() to NULL out our copy of the slots.  The
667         // buffer is gone, so we have nothing to show.
668         //
669         // To be on the safe side we try to release the buffer.
670         ALOGD("repeatLatestBuffer_l: slot was NULL");
671         mConsumer->releaseBuffer(
672                 mLatestBufferId,
673                 mLatestBufferFrameNum,
674                 EGL_NO_DISPLAY,
675                 EGL_NO_SYNC_KHR,
676                 mLatestBufferFence);
677         mLatestBufferId = -1;
678         mLatestBufferFrameNum = 0;
679         mLatestBufferFence = Fence::NO_FENCE;
680         return false;
681     }
682 
683     int cbi = findAvailableCodecBuffer_l();
684     if (cbi < 0) {
685         // No buffers available, bail.
686         ALOGV("repeatLatestBuffer_l: no codec buffers.");
687         return false;
688     }
689 
690     BufferItem item;
691     item.mSlot = mLatestBufferId;
692     item.mFrameNumber = mLatestBufferFrameNum;
693     item.mTimestamp = mRepeatLastFrameTimestamp;
694     item.mFence = mLatestBufferFence;
695 
696     status_t err = submitBuffer_l(item, cbi);
697 
698     if (err != OK) {
699         return false;
700     }
701 
702     ++mLatestBufferUseCount;
703 
704     /* repeat last frame up to kRepeatLastFrameCount times.
705      * in case of static scene, a single repeat might not get rid of encoder
706      * ghosting completely, refresh a couple more times to get better quality
707      */
708     if (--mRepeatLastFrameCount > 0) {
709         mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
710 
711         if (mReflector != NULL) {
712             sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
713             msg->setInt32("generation", ++mRepeatLastFrameGeneration);
714             msg->post(mRepeatAfterUs);
715         }
716     }
717 
718     return true;
719 }
720 
setLatestBuffer_l(const BufferItem & item,bool dropped)721 void GraphicBufferSource::setLatestBuffer_l(
722         const BufferItem &item, bool dropped) {
723     ALOGV("setLatestBuffer_l");
724 
725     if (mLatestBufferId >= 0) {
726         if (mLatestBufferUseCount == 0) {
727             releaseBuffer(mLatestBufferId, mLatestBufferFrameNum,
728                     mBufferSlot[mLatestBufferId], mLatestBufferFence);
729             // mLatestBufferFence will be set to new fence just below
730         }
731     }
732 
733     mLatestBufferId = item.mSlot;
734     mLatestBufferFrameNum = item.mFrameNumber;
735     mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
736 
737     mLatestBufferUseCount = dropped ? 0 : 1;
738     mRepeatBufferDeferred = false;
739     mRepeatLastFrameCount = kRepeatLastFrameCount;
740     mLatestBufferFence = item.mFence;
741 
742     if (mReflector != NULL) {
743         sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
744         msg->setInt32("generation", ++mRepeatLastFrameGeneration);
745         msg->post(mRepeatAfterUs);
746     }
747 }
748 
signalEndOfInputStream()749 status_t GraphicBufferSource::signalEndOfInputStream() {
750     Mutex::Autolock autoLock(mMutex);
751     ALOGV("signalEndOfInputStream: exec=%d avail=%zu eos=%d",
752             mExecuting, mNumFramesAvailable, mEndOfStream);
753 
754     if (mEndOfStream) {
755         ALOGE("EOS was already signaled");
756         return INVALID_OPERATION;
757     }
758 
759     // Set the end-of-stream flag.  If no frames are pending from the
760     // BufferQueue, and a codec buffer is available, and we're executing,
761     // we initiate the EOS from here.  Otherwise, we'll let
762     // codecBufferEmptied() (or omxExecuting) do it.
763     //
764     // Note: if there are no pending frames and all codec buffers are
765     // available, we *must* submit the EOS from here or we'll just
766     // stall since no future events are expected.
767     mEndOfStream = true;
768 
769     if (mExecuting && mNumFramesAvailable == 0) {
770         submitEndOfInputStream_l();
771     }
772 
773     return OK;
774 }
775 
getTimestamp(const BufferItem & item)776 int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) {
777     int64_t timeUs = item.mTimestamp / 1000;
778     timeUs += mInputBufferTimeOffsetUs;
779 
780     if (mTimePerCaptureUs > 0ll
781             && (mTimePerCaptureUs > 2 * mTimePerFrameUs
782             || mTimePerFrameUs > 2 * mTimePerCaptureUs)) {
783         // Time lapse or slow motion mode
784         if (mPrevCaptureUs < 0ll) {
785             // first capture
786             mPrevCaptureUs = timeUs;
787             mPrevFrameUs = timeUs;
788         } else {
789             // snap to nearest capture point
790             int64_t nFrames = (timeUs + mTimePerCaptureUs / 2 - mPrevCaptureUs)
791                     / mTimePerCaptureUs;
792             if (nFrames <= 0) {
793                 // skip this frame as it's too close to previous capture
794                 ALOGV("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
795                 return -1;
796             }
797             mPrevCaptureUs = mPrevCaptureUs + nFrames * mTimePerCaptureUs;
798             mPrevFrameUs += mTimePerFrameUs * nFrames;
799         }
800 
801         ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
802                 static_cast<long long>(timeUs),
803                 static_cast<long long>(mPrevCaptureUs),
804                 static_cast<long long>(mPrevFrameUs));
805 
806         return mPrevFrameUs;
807     } else {
808         int64_t originalTimeUs = timeUs;
809         if (originalTimeUs <= mPrevOriginalTimeUs) {
810                 // Drop the frame if it's going backward in time. Bad timestamp
811                 // could disrupt encoder's rate control completely.
812             ALOGW("Dropping frame that's going backward in time");
813             return -1;
814         }
815 
816         if (mMaxTimestampGapUs > 0ll) {
817             //TODO: Fix the case when mMaxTimestampGapUs and mTimePerCaptureUs are both set.
818 
819             /* Cap timestamp gap between adjacent frames to specified max
820              *
821              * In the scenario of cast mirroring, encoding could be suspended for
822              * prolonged periods. Limiting the pts gap to workaround the problem
823              * where encoder's rate control logic produces huge frames after a
824              * long period of suspension.
825              */
826             if (mPrevOriginalTimeUs >= 0ll) {
827                 int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
828                 timeUs = (timestampGapUs < mMaxTimestampGapUs ?
829                     timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
830                 mOriginalTimeUs.add(timeUs, originalTimeUs);
831                 ALOGV("IN  timestamp: %lld -> %lld",
832                     static_cast<long long>(originalTimeUs),
833                     static_cast<long long>(timeUs));
834             }
835         }
836 
837         mPrevOriginalTimeUs = originalTimeUs;
838         mPrevModifiedTimeUs = timeUs;
839     }
840 
841     return timeUs;
842 }
843 
submitBuffer_l(const BufferItem & item,int cbi)844 status_t GraphicBufferSource::submitBuffer_l(const BufferItem &item, int cbi) {
845     ALOGV("submitBuffer_l cbi=%d", cbi);
846 
847     int64_t timeUs = getTimestamp(item);
848     if (timeUs < 0ll) {
849         return UNKNOWN_ERROR;
850     }
851 
852     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
853     codecBuffer.mGraphicBuffer = mBufferSlot[item.mSlot];
854     codecBuffer.mSlot = item.mSlot;
855     codecBuffer.mFrameNumber = item.mFrameNumber;
856 
857     OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
858     sp<GraphicBuffer> buffer = codecBuffer.mGraphicBuffer;
859     status_t err = mNodeInstance->emptyGraphicBuffer(
860             header, buffer, OMX_BUFFERFLAG_ENDOFFRAME, timeUs,
861             item.mFence->isValid() ? item.mFence->dup() : -1);
862     if (err != OK) {
863         ALOGW("WARNING: emptyNativeWindowBuffer failed: 0x%x", err);
864         codecBuffer.mGraphicBuffer = NULL;
865         return err;
866     }
867 
868     ALOGV("emptyNativeWindowBuffer succeeded, h=%p p=%p buf=%p bufhandle=%p",
869             header, header->pBuffer, buffer->getNativeBuffer(), buffer->handle);
870     return OK;
871 }
872 
submitEndOfInputStream_l()873 void GraphicBufferSource::submitEndOfInputStream_l() {
874     CHECK(mEndOfStream);
875     if (mEndOfStreamSent) {
876         ALOGV("EOS already sent");
877         return;
878     }
879 
880     int cbi = findAvailableCodecBuffer_l();
881     if (cbi < 0) {
882         ALOGV("submitEndOfInputStream_l: no codec buffers available");
883         return;
884     }
885 
886     // We reject any additional incoming graphic buffers, so there's no need
887     // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as
888     // in-use.
889     CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
890 
891     OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
892     status_t err = mNodeInstance->emptyGraphicBuffer(
893             header, NULL /* buffer */, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
894             0 /* timestamp */, -1 /* fenceFd */);
895     if (err != OK) {
896         ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
897     } else {
898         ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d",
899                 header, cbi);
900         mEndOfStreamSent = true;
901     }
902 }
903 
findAvailableCodecBuffer_l()904 int GraphicBufferSource::findAvailableCodecBuffer_l() {
905     CHECK(mCodecBuffers.size() > 0);
906 
907     for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
908         if (mCodecBuffers[i].mGraphicBuffer == NULL) {
909             return i;
910         }
911     }
912     return -1;
913 }
914 
findMatchingCodecBuffer_l(const OMX_BUFFERHEADERTYPE * header)915 int GraphicBufferSource::findMatchingCodecBuffer_l(
916         const OMX_BUFFERHEADERTYPE* header) {
917     for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) {
918         if (mCodecBuffers[i].mHeader == header) {
919             return i;
920         }
921     }
922     return -1;
923 }
924 
925 /*
926  * Releases an acquired buffer back to the consumer for either persistent
927  * or non-persistent surfaces.
928  *
929  * id: buffer slot to release (in persistent case the id might be changed)
930  * frameNum: frame number of the frame being released
931  * buffer: GraphicBuffer pointer to release (note this must not be & as we
932  *         will clear the original mBufferSlot in persistent case)
933  * fence: fence of the frame being released
934  */
releaseBuffer(int & id,uint64_t frameNum,const sp<GraphicBuffer> buffer,const sp<Fence> & fence)935 void GraphicBufferSource::releaseBuffer(
936         int &id, uint64_t frameNum,
937         const sp<GraphicBuffer> buffer, const sp<Fence> &fence) {
938     if (mIsPersistent) {
939         mConsumer->detachBuffer(id);
940         mBufferSlot[id] = NULL;
941 
942         if (mConsumer->attachBuffer(&id, buffer) == OK) {
943             mConsumer->releaseBuffer(
944                     id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
945         }
946     } else {
947         mConsumer->releaseBuffer(
948                 id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
949     }
950     id = -1; // invalidate id
951     mNumBufferAcquired--;
952 }
953 
954 // BufferQueue::ConsumerListener callback
onFrameAvailable(const BufferItem &)955 void GraphicBufferSource::onFrameAvailable(const BufferItem& /*item*/) {
956     Mutex::Autolock autoLock(mMutex);
957 
958     ALOGV("onFrameAvailable exec=%d avail=%zu",
959             mExecuting, mNumFramesAvailable);
960 
961     if (mEndOfStream || mSuspended) {
962         if (mEndOfStream) {
963             // This should only be possible if a new buffer was queued after
964             // EOS was signaled, i.e. the app is misbehaving.
965 
966             ALOGW("onFrameAvailable: EOS is set, ignoring frame");
967         } else {
968             ALOGV("onFrameAvailable: suspended, ignoring frame");
969         }
970 
971         BufferItem item;
972         status_t err = mConsumer->acquireBuffer(&item, 0);
973         if (err == OK) {
974             mNumBufferAcquired++;
975 
976             // If this is the first time we're seeing this buffer, add it to our
977             // slot table.
978             if (item.mGraphicBuffer != NULL) {
979                 ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mSlot);
980                 mBufferSlot[item.mSlot] = item.mGraphicBuffer;
981             }
982 
983             releaseBuffer(item.mSlot, item.mFrameNumber,
984                     item.mGraphicBuffer, item.mFence);
985         }
986         return;
987     }
988 
989     mNumFramesAvailable++;
990 
991     mRepeatBufferDeferred = false;
992     ++mRepeatLastFrameGeneration;
993 
994     if (mExecuting) {
995         fillCodecBuffer_l();
996     }
997 }
998 
999 // BufferQueue::ConsumerListener callback
onBuffersReleased()1000 void GraphicBufferSource::onBuffersReleased() {
1001     Mutex::Autolock lock(mMutex);
1002 
1003     uint64_t slotMask;
1004     if (mConsumer->getReleasedBuffers(&slotMask) != NO_ERROR) {
1005         ALOGW("onBuffersReleased: unable to get released buffer set");
1006         slotMask = 0xffffffffffffffffULL;
1007     }
1008 
1009     ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
1010 
1011     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
1012         if ((slotMask & 0x01) != 0) {
1013             mBufferSlot[i] = NULL;
1014         }
1015         slotMask >>= 1;
1016     }
1017 }
1018 
1019 // BufferQueue::ConsumerListener callback
onSidebandStreamChanged()1020 void GraphicBufferSource::onSidebandStreamChanged() {
1021     ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
1022 }
1023 
setDefaultDataSpace(android_dataspace dataSpace)1024 void GraphicBufferSource::setDefaultDataSpace(android_dataspace dataSpace) {
1025     // no need for mutex as we are not yet running
1026     ALOGD("setting dataspace: %#x", dataSpace);
1027     mConsumer->setDefaultBufferDataSpace(dataSpace);
1028     mLastDataSpace = dataSpace;
1029 }
1030 
setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs)1031 status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(
1032         int64_t repeatAfterUs) {
1033     Mutex::Autolock autoLock(mMutex);
1034 
1035     if (mExecuting || repeatAfterUs <= 0ll) {
1036         return INVALID_OPERATION;
1037     }
1038 
1039     mRepeatAfterUs = repeatAfterUs;
1040 
1041     return OK;
1042 }
1043 
setMaxTimestampGapUs(int64_t maxGapUs)1044 status_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) {
1045     Mutex::Autolock autoLock(mMutex);
1046 
1047     if (mExecuting || maxGapUs <= 0ll) {
1048         return INVALID_OPERATION;
1049     }
1050 
1051     mMaxTimestampGapUs = maxGapUs;
1052 
1053     return OK;
1054 }
1055 
setInputBufferTimeOffset(int64_t timeOffsetUs)1056 status_t GraphicBufferSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
1057     Mutex::Autolock autoLock(mMutex);
1058 
1059     // timeOffsetUs must be negative for adjustment.
1060     if (timeOffsetUs >= 0ll) {
1061         return INVALID_OPERATION;
1062     }
1063 
1064     mInputBufferTimeOffsetUs = timeOffsetUs;
1065     return OK;
1066 }
1067 
setMaxFps(float maxFps)1068 status_t GraphicBufferSource::setMaxFps(float maxFps) {
1069     Mutex::Autolock autoLock(mMutex);
1070 
1071     if (mExecuting) {
1072         return INVALID_OPERATION;
1073     }
1074 
1075     mFrameDropper = new FrameDropper();
1076     status_t err = mFrameDropper->setMaxFrameRate(maxFps);
1077     if (err != OK) {
1078         mFrameDropper.clear();
1079         return err;
1080     }
1081 
1082     return OK;
1083 }
1084 
setSkipFramesBeforeUs(int64_t skipFramesBeforeUs)1085 void GraphicBufferSource::setSkipFramesBeforeUs(int64_t skipFramesBeforeUs) {
1086     Mutex::Autolock autoLock(mMutex);
1087 
1088     mSkipFramesBeforeNs =
1089             (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll;
1090 }
1091 
setTimeLapseConfig(const TimeLapseConfig & config)1092 status_t GraphicBufferSource::setTimeLapseConfig(const TimeLapseConfig &config) {
1093     Mutex::Autolock autoLock(mMutex);
1094 
1095     if (mExecuting || config.mTimePerFrameUs <= 0ll || config.mTimePerCaptureUs <= 0ll) {
1096         return INVALID_OPERATION;
1097     }
1098 
1099     mTimePerFrameUs = config.mTimePerFrameUs;
1100     mTimePerCaptureUs = config.mTimePerCaptureUs;
1101 
1102     return OK;
1103 }
1104 
setColorAspects(const ColorAspects & aspects)1105 void GraphicBufferSource::setColorAspects(const ColorAspects &aspects) {
1106     Mutex::Autolock autoLock(mMutex);
1107     mColorAspects = aspects;
1108     ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
1109             aspects.mRange, asString(aspects.mRange),
1110             aspects.mPrimaries, asString(aspects.mPrimaries),
1111             aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
1112             aspects.mTransfer, asString(aspects.mTransfer));
1113 }
1114 
onMessageReceived(const sp<AMessage> & msg)1115 void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
1116     switch (msg->what()) {
1117         case kWhatRepeatLastFrame:
1118         {
1119             Mutex::Autolock autoLock(mMutex);
1120 
1121             int32_t generation;
1122             CHECK(msg->findInt32("generation", &generation));
1123 
1124             if (generation != mRepeatLastFrameGeneration) {
1125                 // stale
1126                 break;
1127             }
1128 
1129             if (!mExecuting || mNumFramesAvailable > 0) {
1130                 break;
1131             }
1132 
1133             bool success = repeatLatestBuffer_l();
1134 
1135             if (success) {
1136                 ALOGV("repeatLatestBuffer_l SUCCESS");
1137             } else {
1138                 ALOGV("repeatLatestBuffer_l FAILURE");
1139                 mRepeatBufferDeferred = true;
1140             }
1141             break;
1142         }
1143 
1144         default:
1145             TRESPASS();
1146     }
1147 }
1148 
1149 }  // namespace android
1150