summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libstagefright/ACodec.cpp1
-rw-r--r--media/libstagefright/MediaCodec.cpp22
-rw-r--r--media/libstagefright/MediaSync.cpp14
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.cpp21
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.h1
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp11
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp29
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h3
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);