diff options
-rw-r--r-- | media/libstagefright/ACodec.cpp | 1 | ||||
-rw-r--r-- | media/libstagefright/MediaCodec.cpp | 22 | ||||
-rw-r--r-- | media/libstagefright/MediaSync.cpp | 14 | ||||
-rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.cpp | 21 | ||||
-rw-r--r-- | media/libstagefright/omx/GraphicBufferSource.h | 1 | ||||
-rw-r--r-- | media/libstagefright/omx/OMXNodeInstance.cpp | 11 | ||||
-rw-r--r-- | services/camera/libcameraservice/device3/Camera3Device.cpp | 29 | ||||
-rw-r--r-- | services/camera/libcameraservice/device3/Camera3Device.h | 3 |
8 files changed, 64 insertions, 38 deletions
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index c6e45af..7452e4b 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -5242,6 +5242,7 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) { if (err == OK) { info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; } else { + ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err); mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err)); info->mStatus = BufferInfo::OWNED_BY_US; // keeping read fence as write fence to avoid clobbering diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index b576cd9..69f44ed 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -2528,7 +2528,25 @@ status_t MediaCodec::connectToSurface(const sp<Surface> &surface) { err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); if (err == BAD_VALUE) { ALOGI("native window already connected. Assuming no change of surface"); - } else if (err != OK) { + } else if (err == OK) { + // Require a fresh set of buffers after each connect by using a unique generation + // number. Rely on the fact that max supported process id by Linux is 2^22. + // PID is never 0 so we don't have to worry that we use the default generation of 0. + // TODO: come up with a unique scheme if other producers also set the generation number. + static uint32_t mSurfaceGeneration = 0; + uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1)); + surface->setGenerationNumber(generation); + ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation); + + // HACK: clear any free buffers. Remove when connect will automatically do this. + // This is needed as the consumer may be holding onto stale frames that it can reattach + // to this surface after disconnect/connect, and those free frames would inherit the new + // generation number. Disconnecting after setting a unique generation prevents this. + native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA); + err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); + } + + if (err != OK) { ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err); } } @@ -2538,6 +2556,8 @@ status_t MediaCodec::connectToSurface(const sp<Surface> &surface) { status_t MediaCodec::disconnectFromSurface() { status_t err = OK; if (mSurface != NULL) { + // Resetting generation is not technically needed, but there is no need to keep it either + mSurface->setGenerationNumber(0); err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); if (err != OK) { ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err); diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp index b402e48..52077a7 100644 --- a/media/libstagefright/MediaSync.cpp +++ b/media/libstagefright/MediaSync.cpp @@ -558,7 +558,6 @@ void MediaSync::onFrameAvailableFromInput() { return; } } - ++mNumOutstandingBuffers; // Acquire and detach the buffer from the input. BufferItem bufferItem; @@ -567,6 +566,7 @@ void MediaSync::onFrameAvailableFromInput() { ALOGE("acquiring buffer from input failed (%d)", status); return; } + ++mNumOutstandingBuffers; ALOGV("acquired buffer %#llx from input", (long long)bufferItem.mGraphicBuffer->getId()); @@ -608,6 +608,7 @@ void MediaSync::renderOneBufferItem_l( const BufferItem &bufferItem) { // Attach and queue the buffer to the output. int slot; + mOutput->setGenerationNumber(bufferItem.mGraphicBuffer->getGenerationNumber()); status_t status = mOutput->attachBuffer(&slot, bufferItem.mGraphicBuffer); ALOGE_IF(status != NO_ERROR, "attaching buffer to output failed (%d)", status); if (status == NO_ERROR) { @@ -695,16 +696,13 @@ void MediaSync::returnBufferToInput_l( ALOGE_IF(status != NO_ERROR, "releasing buffer to input failed (%d)", status); } - if (status != NO_ERROR) { - // TODO: do we need to try to return this buffer later? - return; - } - - ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId()); - // Notify any waiting onFrameAvailable calls. --mNumOutstandingBuffers; mReleaseCondition.signal(); + + if (status == NO_ERROR) { + ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId()); + } } void MediaSync::onAbandoned_l(bool isInput) { diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp index 19f0a37..1a7dc9d 100644 --- a/media/libstagefright/omx/GraphicBufferSource.cpp +++ b/media/libstagefright/omx/GraphicBufferSource.cpp @@ -111,6 +111,7 @@ GraphicBufferSource::GraphicBufferSource( uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount, + uint32_t consumerUsage, const sp<IGraphicBufferConsumer> &consumer) : mInitCheck(UNKNOWN_ERROR), mNodeInstance(nodeInstance), @@ -154,16 +155,10 @@ GraphicBufferSource::GraphicBufferSource( BufferQueue::createBufferQueue(&mProducer, &mConsumer); mConsumer->setConsumerName(name); - // query consumer usage bits from encoder, but always add HW_VIDEO_ENCODER + // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER // for backward compatibility. - uint32_t usageBits; - status_t err = mNodeInstance->getParameter( - (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits, sizeof(usageBits)); - if (err != OK) { - usageBits = 0; - } - usageBits |= GRALLOC_USAGE_HW_VIDEO_ENCODER; - mConsumer->setConsumerUsageBits(usageBits); + consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER; + mConsumer->setConsumerUsageBits(consumerUsage); mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount); if (mInitCheck != NO_ERROR) { @@ -848,13 +843,15 @@ void GraphicBufferSource::releaseBuffer( mConsumer->detachBuffer(id); mBufferSlot[id] = NULL; - mConsumer->attachBuffer(&id, buffer); - mConsumer->releaseBuffer( - id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence); + if (mConsumer->attachBuffer(&id, buffer) == OK) { + mConsumer->releaseBuffer( + id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence); + } } else { mConsumer->releaseBuffer( id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence); } + id = -1; // invalidate id mNumBufferAcquired--; } diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h index 3f64088..2f929d9 100644 --- a/media/libstagefright/omx/GraphicBufferSource.h +++ b/media/libstagefright/omx/GraphicBufferSource.h @@ -55,6 +55,7 @@ public: uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount, + uint32_t consumerUsage, const sp<IGraphicBufferConsumer> &consumer = NULL ); diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 95549a4..9f1c5d8 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -834,7 +834,8 @@ status_t OMXNodeInstance::updateGraphicBufferInMeta_l( } CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p", - portString(portIndex), portIndex, buffer, graphicBuffer->handle); + portString(portIndex), portIndex, buffer, + graphicBuffer == NULL ? NULL : graphicBuffer->handle); return OK; } @@ -885,10 +886,18 @@ status_t OMXNodeInstance::createGraphicBufferSource( return INVALID_OPERATION; } + uint32_t usageBits; + oerr = OMX_GetParameter( + mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits); + if (oerr != OMX_ErrorNone) { + usageBits = 0; + } + sp<GraphicBufferSource> bufferSource = new GraphicBufferSource(this, def.format.video.nFrameWidth, def.format.video.nFrameHeight, def.nBufferCountActual, + usageBits, bufferConsumer); if ((err = bufferSource->initCheck()) != OK) { diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 4b55dad..9e73b5c 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -164,9 +164,17 @@ status_t Camera3Device::initialize(CameraModule *module) return res; } - /** Start up request queue thread */ + bool aeLockAvailable = false; + camera_metadata_ro_entry aeLockAvailableEntry; + res = find_camera_metadata_ro_entry(info.static_camera_characteristics, + ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailableEntry); + if (res == OK && aeLockAvailableEntry.count > 0) { + aeLockAvailable = (aeLockAvailableEntry.data.u8[0] == + ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE); + } - mRequestThread = new RequestThread(this, mStatusTracker, device); + /** Start up request queue thread */ + mRequestThread = new RequestThread(this, mStatusTracker, device, aeLockAvailable); res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string()); if (res != OK) { SET_ERR_L("Unable to start request queue thread: %s (%d)", @@ -2472,7 +2480,8 @@ CameraMetadata Camera3Device::getLatestRequestLocked() { Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent, sp<StatusTracker> statusTracker, - camera3_device_t *hal3Device) : + camera3_device_t *hal3Device, + bool aeLockAvailable) : Thread(/*canCallJava*/false), mParent(parent), mStatusTracker(statusTracker), @@ -2485,19 +2494,9 @@ Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent, mLatestRequestId(NAME_NOT_FOUND), mCurrentAfTriggerId(0), mCurrentPreCaptureTriggerId(0), - mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES) { + mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES), + mAeLockAvailable(aeLockAvailable) { mStatusId = statusTracker->addComponent(); - - mAeLockAvailable = false; - sp<Camera3Device> p = parent.promote(); - if (p != NULL) { - camera_metadata_ro_entry aeLockAvailable = - p->info().find(ANDROID_CONTROL_AE_LOCK_AVAILABLE); - if (aeLockAvailable.count > 0) { - mAeLockAvailable = (aeLockAvailable.data.u8[0] == - ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE); - } - } } void Camera3Device::RequestThread::setNotificationListener( diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index bb4bcc4..31b6132 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -389,7 +389,8 @@ class Camera3Device : RequestThread(wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker, - camera3_device_t *hal3Device); + camera3_device_t *hal3Device, + bool aeLockAvailable); void setNotificationListener(NotificationListener *listener); |