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(¶ms);
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, ¶ms, 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, ¶ms, sizeof(params));
548 if (err == OK) {
549 err = mNodeInstance->getConfig(index, ¶ms, 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