summaryrefslogtreecommitdiffstats
path: root/services/camera
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2012-08-21 13:30:45 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-08-21 17:45:25 -0700
commit30e65e7e2ec01e13e45b5e38552a34d2fbb3f866 (patch)
treef028cfdc6fc9d8309a5ba1cb0cb6eb020bbc3964 /services/camera
parent76dc8dacbb3e2a8c91cb526293270f9093cf8f8b (diff)
downloadframeworks_av-30e65e7e2ec01e13e45b5e38552a34d2fbb3f866.zip
frameworks_av-30e65e7e2ec01e13e45b5e38552a34d2fbb3f866.tar.gz
frameworks_av-30e65e7e2ec01e13e45b5e38552a34d2fbb3f866.tar.bz2
Camera2: Replace MediaConsumer with BufferItemConsumer.
Get rid of MediaConsumer, which was largely duplicated code, and replace it with the simpler BufferItemConsumer. Bug: 6243944 Change-Id: I242d80c5fe39f2ee581ec8bb46f362997d994b0a
Diffstat (limited to 'services/camera')
-rw-r--r--services/camera/libcameraservice/Android.mk3
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp65
-rw-r--r--services/camera/libcameraservice/Camera2Client.h13
-rw-r--r--services/camera/libcameraservice/MediaConsumer.cpp198
-rw-r--r--services/camera/libcameraservice/MediaConsumer.h126
5 files changed, 60 insertions, 345 deletions
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index c14ae22..8cccf49 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -10,8 +10,7 @@ LOCAL_SRC_FILES:= \
CameraService.cpp \
CameraClient.cpp \
Camera2Client.cpp \
- Camera2Device.cpp \
- MediaConsumer.cpp
+ Camera2Device.cpp
LOCAL_SHARED_LIBRARIES:= \
libui \
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 66d8a50..aa30501 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -920,6 +920,9 @@ void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
Mutex::Autolock icl(mICameraLock);
status_t res;
if ( checkPid(__FUNCTION__) != OK) return;
+
+ LockedParameters::Key k(mParameters);
+
// Make sure this is for the current heap
ssize_t offset;
size_t size;
@@ -937,16 +940,36 @@ void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
__FUNCTION__, mCameraId, type, kMetadataBufferTypeGrallocSource);
return;
}
- buffer_handle_t imgBuffer = *(buffer_handle_t*)(data + 4);
+
+ // Release the buffer back to the recording queue
+
+ buffer_handle_t imgHandle = *(buffer_handle_t*)(data + 4);
+
+ size_t itemIndex;
+ for (itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
+ const BufferItemConsumer::BufferItem item = mRecordingBuffers[itemIndex];
+ if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT &&
+ item.mGraphicBuffer->handle == imgHandle) {
+ break;
+ }
+ }
+ if (itemIndex == mRecordingBuffers.size()) {
+ ALOGE("%s: Camera %d: Can't find buffer_handle_t %p in list of "
+ "outstanding buffers", __FUNCTION__, mCameraId, imgHandle);
+ return;
+ }
+
ALOGV("%s: Camera %d: Freeing buffer_handle_t %p", __FUNCTION__, mCameraId,
- imgBuffer);
- res = mRecordingConsumer->freeBuffer(imgBuffer);
+ imgHandle);
+
+ res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to free recording frame (buffer_handle_t: %p):"
"%s (%d)",
- __FUNCTION__, mCameraId, imgBuffer, strerror(-res), res);
+ __FUNCTION__, mCameraId, imgHandle, strerror(-res), res);
return;
}
+ mRecordingBuffers.replaceAt(itemIndex);
mRecordingHeapFree++;
}
@@ -2313,13 +2336,14 @@ void Camera2Client::onRecordingFrameAvailable() {
{
LockedParameters::Key k(mParameters);
- buffer_handle_t imgBuffer;
- res = mRecordingConsumer->getNextBuffer(&imgBuffer, &timestamp);
+ BufferItemConsumer::BufferItem imgBuffer;
+ res = mRecordingConsumer->acquireBuffer(&imgBuffer);
if (res != OK) {
ALOGE("%s: Camera %d: Error receiving recording buffer: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return;
}
+ timestamp = imgBuffer.mTimestamp;
mRecordingFrameCount++;
ALOGV("OnRecordingFrame: Frame %d", mRecordingFrameCount);
@@ -2330,7 +2354,7 @@ void Camera2Client::onRecordingFrameAvailable() {
ALOGV("%s: Camera %d: Discarding recording image buffers received after "
"recording done",
__FUNCTION__, mCameraId);
- mRecordingConsumer->freeBuffer(imgBuffer);
+ mRecordingConsumer->releaseBuffer(imgBuffer);
return;
}
@@ -2345,9 +2369,20 @@ void Camera2Client::onRecordingFrameAvailable() {
if (mRecordingHeap->mHeap->getSize() == 0) {
ALOGE("%s: Camera %d: Unable to allocate memory for recording",
__FUNCTION__, mCameraId);
- mRecordingConsumer->freeBuffer(imgBuffer);
+ mRecordingConsumer->releaseBuffer(imgBuffer);
return;
}
+ for (size_t i = 0; i < mRecordingBuffers.size(); i++) {
+ if (mRecordingBuffers[i].mBuf !=
+ BufferItemConsumer::INVALID_BUFFER_SLOT) {
+ ALOGE("%s: Camera %d: Non-empty recording buffers list!",
+ __FUNCTION__, mCameraId);
+ }
+ }
+ mRecordingBuffers.clear();
+ mRecordingBuffers.setCapacity(mRecordingHeapCount);
+ mRecordingBuffers.insertAt(0, mRecordingHeapCount);
+
mRecordingHeapHead = 0;
mRecordingHeapFree = mRecordingHeapCount;
}
@@ -2355,7 +2390,7 @@ void Camera2Client::onRecordingFrameAvailable() {
if ( mRecordingHeapFree == 0) {
ALOGE("%s: Camera %d: No free recording buffers, dropping frame",
__FUNCTION__, mCameraId);
- mRecordingConsumer->freeBuffer(imgBuffer);
+ mRecordingConsumer->releaseBuffer(imgBuffer);
return;
}
@@ -2374,10 +2409,11 @@ void Camera2Client::onRecordingFrameAvailable() {
uint8_t *data = (uint8_t*)heap->getBase() + offset;
uint32_t type = kMetadataBufferTypeGrallocSource;
- memcpy(data, &type, 4);
- memcpy(data + 4, &imgBuffer, sizeof(buffer_handle_t));
+ *((uint32_t*)data) = type;
+ *((buffer_handle_t*)(data + 4)) = imgBuffer.mGraphicBuffer->handle;
ALOGV("%s: Camera %d: Sending out buffer_handle_t %p",
- __FUNCTION__, mCameraId, imgBuffer);
+ __FUNCTION__, mCameraId, imgBuffer.mGraphicBuffer->handle);
+ mRecordingBuffers.replaceAt(imgBuffer, heapIdx);
recordingHeap = mRecordingHeap;
}
@@ -3530,7 +3566,10 @@ status_t Camera2Client::updateRecordingStream(const Parameters &params) {
// Create CPU buffer queue endpoint. We need one more buffer here so that we can
// always acquire and free a buffer when the heap is full; otherwise the consumer
// will have buffers in flight we'll never clear out.
- mRecordingConsumer = new MediaConsumer(mRecordingHeapCount + 1);
+ mRecordingConsumer = new BufferItemConsumer(
+ GRALLOC_USAGE_HW_VIDEO_ENCODER,
+ mRecordingHeapCount + 1,
+ true);
mRecordingConsumer->setFrameAvailableListener(new RecordingWaiter(this));
mRecordingConsumer->setName(String8("Camera2Client::RecordingConsumer"));
mRecordingWindow = new SurfaceTextureClient(
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index fa300e7..028d458 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -23,7 +23,7 @@
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <gui/CpuConsumer.h>
-#include "MediaConsumer.h"
+#include <gui/BufferItemConsumer.h>
namespace android {
@@ -363,11 +363,11 @@ private:
int mRecordingStreamId;
int mRecordingFrameCount;
- sp<MediaConsumer> mRecordingConsumer;
+ sp<BufferItemConsumer> mRecordingConsumer;
sp<ANativeWindow> mRecordingWindow;
// Simple listener that forwards frame available notifications from
// a CPU consumer to the recording notification
- class RecordingWaiter: public MediaConsumer::FrameAvailableListener {
+ class RecordingWaiter: public BufferItemConsumer::FrameAvailableListener {
public:
RecordingWaiter(Camera2Client *parent) : mParent(parent) {}
void onFrameAvailable() { mParent->onRecordingFrameAvailable(); }
@@ -380,6 +380,7 @@ private:
static const size_t kDefaultRecordingHeapCount = 8;
size_t mRecordingHeapCount;
+ Vector<BufferItemConsumer::BufferItem> mRecordingBuffers;
size_t mRecordingHeapHead, mRecordingHeapFree;
// Handle new recording image buffers
void onRecordingFrameAvailable();
@@ -442,9 +443,9 @@ private:
// Update parameters all requests use, based on mParameters
status_t updateRequestCommon(camera_metadata_t *request, const Parameters &params);
- // Map from sensor active array pixel coordinates to normalized camera parameter coordinates
- // The former are (0,0)-(array width - 1, array height - 1), the latter from
- // (-1000,-1000)-(1000,1000)
+ // Map from sensor active array pixel coordinates to normalized camera
+ // parameter coordinates. The former are (0,0)-(array width - 1, array height
+ // - 1), the latter from (-1000,-1000)-(1000,1000)
int arrayXToNormalized(int width) const;
int arrayYToNormalized(int height) const;
diff --git a/services/camera/libcameraservice/MediaConsumer.cpp b/services/camera/libcameraservice/MediaConsumer.cpp
deleted file mode 100644
index a5fe302..0000000
--- a/services/camera/libcameraservice/MediaConsumer.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaConsumer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Log.h>
-
-#include "MediaConsumer.h"
-
-#define MC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define MC_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define MC_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define MC_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define MC_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
-
-namespace android {
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-MediaConsumer::MediaConsumer(uint32_t maxLockedBuffers) :
- mMaxLockedBuffers(maxLockedBuffers),
- mCurrentLockedBuffers(0)
-{
- mName = String8::format("mc-unnamed-%d-%d", getpid(),
- createProcessUniqueId());
-
- mBufferQueue = new BufferQueue(true);
-
- wp<BufferQueue::ConsumerListener> listener;
- sp<BufferQueue::ConsumerListener> proxy;
- listener = static_cast<BufferQueue::ConsumerListener*>(this);
- proxy = new BufferQueue::ProxyConsumerListener(listener);
-
- status_t err = mBufferQueue->consumerConnect(proxy);
- if (err != NO_ERROR) {
- ALOGE("MediaConsumer: error connecting to BufferQueue: %s (%d)",
- strerror(-err), err);
- } else {
- mBufferQueue->setSynchronousMode(true);
- mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
- mBufferQueue->setConsumerName(mName);
- }
-}
-
-MediaConsumer::~MediaConsumer()
-{
- Mutex::Autolock _l(mMutex);
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
- mBufferQueue->consumerDisconnect();
- mBufferQueue.clear();
-}
-
-void MediaConsumer::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- mName = name;
- mBufferQueue->setConsumerName(name);
-}
-
-status_t MediaConsumer::getNextBuffer(buffer_handle_t *buffer, nsecs_t *timestamp) {
- status_t err;
-
- if (!buffer) return BAD_VALUE;
- if (mCurrentLockedBuffers == mMaxLockedBuffers) {
- MC_LOGV("Too many buffers (max %d)", mCurrentLockedBuffers);
- return INVALID_OPERATION;
- }
-
- BufferQueue::BufferItem b;
-
- Mutex::Autolock _l(mMutex);
-
- err = mBufferQueue->acquireBuffer(&b);
- if (err != OK) {
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- MC_LOGV("No buffer available");
- return BAD_VALUE;
- } else {
- MC_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
- return err;
- }
- }
-
- int buf = b.mBuf;
-
- if (b.mGraphicBuffer != NULL) {
- mBufferSlot[buf] = b.mGraphicBuffer;
- }
-
- if (b.mFence.get()) {
- err = b.mFence->wait(Fence::TIMEOUT_NEVER);
- if (err != OK) {
- MC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
- strerror(-err), err);
- return err;
- }
- }
-
- *buffer = mBufferSlot[buf]->handle;
- *timestamp = b.mTimestamp;
-
- mCurrentLockedBuffers++;
- MC_LOGV("getNextBuffer: %d buffers in use", mCurrentLockedBuffers);
- return OK;
-}
-
-status_t MediaConsumer::freeBuffer(buffer_handle_t buffer) {
- Mutex::Autolock _l(mMutex);
- int buf = 0;
- status_t err;
-
- for (; buf < BufferQueue::NUM_BUFFER_SLOTS; buf++) {
- if (buffer == mBufferSlot[buf]->handle) break;
- }
- if (buf == BufferQueue::NUM_BUFFER_SLOTS) {
- MC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
- return BAD_VALUE;
- }
-
- err = mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
- Fence::NO_FENCE);
- if (err == BufferQueue::STALE_BUFFER_SLOT) {
- freeBufferLocked(buf);
- } else if (err != OK) {
- MC_LOGE("%s: Unable to release graphic buffer %d to queue", __FUNCTION__,
- buf);
- return err;
- }
- mCurrentLockedBuffers--;
- MC_LOGV("freeBuffer: %d buffers in use", mCurrentLockedBuffers);
-
- return OK;
-}
-
-void MediaConsumer::setFrameAvailableListener(
- const sp<FrameAvailableListener>& listener) {
- MC_LOGV("setFrameAvailableListener");
- Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = listener;
-}
-
-
-void MediaConsumer::onFrameAvailable() {
- MC_LOGV("onFrameAvailable");
- sp<FrameAvailableListener> listener;
- { // scope for the lock
- Mutex::Autolock _l(mMutex);
- listener = mFrameAvailableListener;
- }
-
- if (listener != NULL) {
- MC_LOGV("actually calling onFrameAvailable");
- listener->onFrameAvailable();
- }
-}
-
-void MediaConsumer::onBuffersReleased() {
- MC_LOGV("onBuffersReleased");
-
- Mutex::Autolock lock(mMutex);
-
- uint32_t mask = 0;
- mBufferQueue->getReleasedBuffers(&mask);
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- if (mask & (1 << i)) {
- freeBufferLocked(i);
- }
- }
-
-}
-
-status_t MediaConsumer::freeBufferLocked(int buf) {
- status_t err = OK;
-
- mBufferSlot[buf] = NULL;
- return err;
-}
-
-} // namespace android
diff --git a/services/camera/libcameraservice/MediaConsumer.h b/services/camera/libcameraservice/MediaConsumer.h
deleted file mode 100644
index 3377d94..0000000
--- a/services/camera/libcameraservice/MediaConsumer.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SERVERS_CAMERA_MEDIACONSUMER_H
-#define ANDROID_SERVERS_CAMERA_MEDIACONSUMER_H
-
-#include <gui/BufferQueue.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#define ANDROID_GRAPHICS_MEDIACONSUMER_JNI_ID "mMediaConsumer"
-
-namespace android {
-
-/**
- * MediaConsumer is a BufferQueue consumer endpoint that makes it
- * straightforward to bridge Camera 2 to the existing media recording framework.
- * This queue is synchronous by default.
- *
- * TODO: This is a temporary replacement for the full camera->media recording
- * path using SurfaceMediaEncoder or equivalent.
- */
-
-class MediaConsumer: public virtual RefBase,
- protected BufferQueue::ConsumerListener
-{
- public:
- struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called each time an additional frame becomes
- // available for consumption. A new frame queued will always trigger the
- // callback, whether the queue is empty or not.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
- };
-
- // Create a new media consumer. The maxBuffers parameter specifies
- // how many buffers can be locked for user access at the same time.
- MediaConsumer(uint32_t maxBuffers);
-
- virtual ~MediaConsumer();
-
- // set the name of the MediaConsumer that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // Gets the next graphics buffer from the producer. Returns BAD_VALUE if no
- // new buffer is available, and INVALID_OPERATION if the maximum number of
- // buffers is already in use.
- //
- // Only a fixed number of buffers can be available at a time, determined by
- // the construction-time maxBuffers parameter. If INVALID_OPERATION is
- // returned by getNextBuffer, then old buffers must be returned to the
- // queue by calling freeBuffer before more buffers can be acquired.
- status_t getNextBuffer(buffer_handle_t *buffer, nsecs_t *timestamp);
-
- // Returns a buffer to the queue, allowing it to be reused. Since
- // only a fixed number of buffers may be locked at a time, old buffers must
- // be released by calling unlockBuffer to ensure new buffers can be acquired by
- // lockNextBuffer.
- status_t freeBuffer(buffer_handle_t buffer);
-
- // setFrameAvailableListener sets the listener object that will be notified
- // when a new frame becomes available.
- void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
-
- sp<ISurfaceTexture> getProducerInterface() const { return mBufferQueue; }
- protected:
-
- // Implementation of the BufferQueue::ConsumerListener interface. These
- // calls are used to notify the MediaConsumer of asynchronous events in the
- // BufferQueue.
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
-
- private:
- // Free local buffer state
- status_t freeBufferLocked(int buf);
-
- // Maximum number of buffers that can be locked at a time
- uint32_t mMaxLockedBuffers;
-
- // mName is a string used to identify the SurfaceTexture in log messages.
- // It can be set by the setName method.
- String8 mName;
-
- // mFrameAvailableListener is the listener object that will be called when a
- // new frame becomes available. If it is not NULL it will be called from
- // queueBuffer.
- sp<FrameAvailableListener> mFrameAvailableListener;
-
- // Underlying buffer queue
- sp<BufferQueue> mBufferQueue;
-
- // Array for caching buffers from the buffer queue
- sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS];
- // Count of currently outstanding buffers
- uint32_t mCurrentLockedBuffers;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of MediaConsumer objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-};
-
-} // namespace android
-
-#endif // ANDROID_SERVERS_CAMERA_MEDIACONSUMER_H