OSDN Git Service

Camera2: Replace MediaConsumer with BufferItemConsumer.
authorEino-Ville Talvala <etalvala@google.com>
Tue, 21 Aug 2012 20:30:45 +0000 (13:30 -0700)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Wed, 22 Aug 2012 00:45:25 +0000 (17:45 -0700)
Get rid of MediaConsumer, which was largely duplicated code, and
replace it with the simpler BufferItemConsumer.

Bug: 6243944
Change-Id: I242d80c5fe39f2ee581ec8bb46f362997d994b0a

services/camera/libcameraservice/Android.mk
services/camera/libcameraservice/Camera2Client.cpp
services/camera/libcameraservice/Camera2Client.h
services/camera/libcameraservice/MediaConsumer.cpp [deleted file]
services/camera/libcameraservice/MediaConsumer.h [deleted file]

index c14ae22..8cccf49 100644 (file)
@@ -10,8 +10,7 @@ LOCAL_SRC_FILES:=               \
     CameraService.cpp \
     CameraClient.cpp \
     Camera2Client.cpp \
-    Camera2Device.cpp \
-    MediaConsumer.cpp
+    Camera2Device.cpp
 
 LOCAL_SHARED_LIBRARIES:= \
     libui \
index 66d8a50..aa30501 100644 (file)
@@ -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(
index fa300e7..028d458 100644 (file)
@@ -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 (file)
index a5fe302..0000000
+++ /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 (file)
index 3377d94..0000000
+++ /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