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