Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a91537e2 authored by Igor Murashkin's avatar Igor Murashkin
Browse files

Camera: ProCamera - implement onResultReceived callback for metadata callbacks

Change-Id: I46775402b007244bc383d6343a620eebbd492aad
parent eb72e179
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@

#include <camera/IProCameraCallbacks.h>

#include <system/camera_metadata.h>

namespace android {

enum {
@@ -35,8 +37,12 @@ enum {
    DATA_CALLBACK,
    DATA_CALLBACK_TIMESTAMP,
    LOCK_STATUS_CHANGED,
    RESULT_RECEIVED,
};

void readMetadata(const Parcel& data, camera_metadata_t** out);
void writeMetadata(Parcel& data, camera_metadata_t* metadata);

class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks>
{
public:
@@ -96,6 +102,15 @@ public:
        remote()->transact(LOCK_STATUS_CHANGED, data, &reply,
                           IBinder::FLAG_ONEWAY);
    }

    void onResultReceived(int32_t frameId, camera_metadata* result) {
        ALOGV("onResultReceived");
        Parcel data, reply;
        data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor());
        data.writeInt32(frameId);
        writeMetadata(data, result);
        remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
    }
};

IMPLEMENT_META_INTERFACE(ProCameraCallbacks,
@@ -152,6 +167,16 @@ status_t BnProCameraCallbacks::onTransact(
            onLockStatusChanged(newLockStatus);
            return NO_ERROR;
        } break;
        case RESULT_RECEIVED: {
            ALOGV("RESULT_RECEIVED");
            CHECK_INTERFACE(IProCameraCallbacks, data, reply);
            int32_t frameId = data.readInt32();
            camera_metadata_t *result = NULL;
            readMetadata(data, &result);
            onResultReceived(frameId, result);
            return NO_ERROR;
            break;
        }
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
+18 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>

#include <system/camera_metadata.h>

namespace android {

// client singleton for camera service binder interface
@@ -198,6 +200,22 @@ void ProCamera::onLockStatusChanged(
    }
}

void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) {
    ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result);

    sp<ProCameraListener> listener;
    {
        Mutex::Autolock _l(mLock);
        listener = mListener;
    }
    if (listener != NULL) {
        listener->onResultReceived(frameId, result);
    } else {
        free_camera_metadata(result);
    }

}

status_t ProCamera::exclusiveTryLock()
{
    sp <IProCameraUser> c = mCamera;
+116 −12
Original line number Diff line number Diff line
@@ -66,8 +66,13 @@ enum ProEvent {
    RELEASED,
    STOLEN,
    BUFFER_RECEIVED,
    RESULT_RECEIVED,
};

inline int ProEvent_Mask(ProEvent e) {
    return (1 << static_cast<int>(e));
}

typedef Vector<ProEvent> EventList;

class ProCameraTestThread : public Thread
@@ -93,6 +98,12 @@ public:
class ProCameraTestListener : public ProCameraListener {

public:
    static const int EVENT_MASK_ALL = 0xFFFFFFFF;

    ProCameraTestListener() {
        mEventMask = EVENT_MASK_ALL;
    }

    status_t WaitForEvent() {
        Mutex::Autolock cal(mConditionMutex);

@@ -136,16 +147,27 @@ public:
        return ev;
    }

    void SetEventMask(int eventMask) {
        Mutex::Autolock al(mListenerMutex);
        mEventMask = eventMask;
    }

private:
    void QueueEvent(ProEvent ev) {
        bool eventAdded = false;
        {
            Mutex::Autolock al(mListenerMutex);

            if (ProEvent_Mask(ev) & mEventMask) {
                mProEventList.push(ev);
                eventAdded = true;
            }
        }


        if (eventAdded) {
            mListenerCondition.broadcast();
        }
    }

protected:

@@ -184,8 +206,11 @@ protected:
        QueueEvent(BUFFER_RECEIVED);

    }
    virtual void onRequestReceived(
    virtual void onResultReceived(int32_t frameId,
                                  camera_metadata* request) {
        dout << "Result received frameId = " << frameId
             << ", requestPtr = " << (void*)request << std::endl;
        QueueEvent(RESULT_RECEIVED);
        free_camera_metadata(request);
    }

@@ -201,6 +226,7 @@ protected:
    Mutex             mListenerMutex;
    Mutex             mConditionMutex;
    Condition         mListenerCondition;
    int               mEventMask;
};

class ProCameraTest : public ::testing::Test {
@@ -309,6 +335,10 @@ TEST_F(ProCameraTest, LockingImmediate) {
        return;
    }

    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
                            ProEvent_Mask(STOLEN)   |
                            ProEvent_Mask(RELEASED));

    EXPECT_FALSE(mCamera->hasExclusiveLock());
    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
    // at this point we definitely have the lock
@@ -332,13 +362,17 @@ TEST_F(ProCameraTest, LockingAsynchronous) {
        return;
    }


    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
                            ProEvent_Mask(STOLEN)   |
                            ProEvent_Mask(RELEASED));

    // TODO: Add another procamera that has a lock here.
    // then we can be test that the lock wont immediately be acquired

    EXPECT_FALSE(mCamera->hasExclusiveLock());
    EXPECT_EQ(OK, mCamera->exclusiveLock());
    // at this point we may or may not have the lock
    // we cant be sure until we get an ACQUIRED event
    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
    // at this point we definitely have the lock

    EXPECT_EQ(OK, mListener->WaitForEvent());
    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
@@ -353,7 +387,7 @@ TEST_F(ProCameraTest, LockingAsynchronous) {
}

// Stream directly to the screen.
TEST_F(ProCameraTest, StreamingImageSingle) {
TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) {
    if (HasFatalFailure()) {
        return;
    }
@@ -433,7 +467,7 @@ TEST_F(ProCameraTest, StreamingImageSingle) {
}

// Stream directly to the screen.
TEST_F(ProCameraTest, StreamingImageDual) {
TEST_F(ProCameraTest, DISABLED_StreamingImageDual) {
    if (HasFatalFailure()) {
        return;
    }
@@ -523,6 +557,9 @@ TEST_F(ProCameraTest, CpuConsumerSingle) {
    if (HasFatalFailure()) {
        return;
    }

    mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));

    int streamId = -1;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
        TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &streamId));
@@ -585,6 +622,9 @@ TEST_F(ProCameraTest, CpuConsumerDual) {
    if (HasFatalFailure()) {
        return;
    }

    mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));

    int streamId = -1;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                            TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId));
@@ -596,8 +636,6 @@ TEST_F(ProCameraTest, CpuConsumerDual) {
    EXPECT_NE(-1, depthStreamId);

    EXPECT_OK(mCamera->exclusiveTryLock());
    EXPECT_EQ(OK, mListener->WaitForEvent());
    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
    /*
    */
    /* iterate in a loop submitting requests every frame.
@@ -657,6 +695,72 @@ TEST_F(ProCameraTest, CpuConsumerDual) {
    EXPECT_OK(mCamera->exclusiveUnlock());
}

TEST_F(ProCameraTest, ResultReceiver) {
    if (HasFatalFailure()) {
        return;
    }

    mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED));
    //FIXME: if this is run right after the previous test we get BUFFER_RECEIVED
    // need to filter out events at read time

    int streamId = -1;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                             TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());
    /*
    */
    /* iterate in a loop submitting requests every frame.
     *  what kind of requests doesnt really matter, just whatever.
     */

    camera_metadata_t *request = NULL;
    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
                                            /*out*/&request));
    EXPECT_NE((void*)NULL, request);

    /*FIXME*/
    if(request == NULL) request = allocate_camera_metadata(10, 100);

    // set the output streams to just this stream ID

    uint8_t allStreams[] = { streamId };
    size_t streamCount = 1;
    camera_metadata_entry_t entry;
    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
    int find = find_camera_metadata_entry(request, tag, &entry);
    if (find == -ENOENT) {
        if (add_camera_metadata_entry(request, tag, &allStreams,
                                      /*data_count*/streamCount) != OK) {
            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
            ASSERT_OK(append_camera_metadata(tmp, request));
            free_camera_metadata(request);
            request = tmp;

            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
                                                /*data_count*/streamCount));
        }
    } else {
        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
                               &allStreams, /*data_count*/streamCount, &entry));
    }

    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));

    // Consume a couple of results
    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
        EXPECT_EQ(OK, mListener->WaitForEvent());
        EXPECT_EQ(RESULT_RECEIVED, mListener->ReadEvent());
    }

    // Done: clean up
    free_camera_metadata(request);
    EXPECT_OK(mCamera->deleteStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

}
}
}
+7 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
#include <utils/Timers.h>
#include <system/camera.h>

struct camera_metadata;

namespace android {

class IProCameraCallbacks: public IInterface
@@ -47,6 +49,11 @@ public:
    };

    virtual void            onLockStatusChanged(LockStatus newLockStatus) = 0;

    /** Missing by design: implementation is client-side in ProCamera.cpp **/
    // virtual void onBufferReceived(int streamId,
    //                               const CpuConsumer::LockedBufer& buf);
    virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0;
};

// ----------------------------------------------------------------------------
+11 −6
Original line number Diff line number Diff line
@@ -49,17 +49,19 @@ public:
    // OnBufferReceived and OnRequestReceived can come in with any order,
    // use android.sensor.timestamp and LockedBuffer.timestamp to correlate them

    // TODO: implement in IProCameraCallbacks, ProCamera2Client

    // A new frame buffer has been received for this stream.
    // -- This callback only fires for createStreamCpu streams
    // -- Use buf.timestamp to correlate with metadata's
    //    android.sensor.timestamp
    // -- The buffer must not be accessed after this function call completes
    virtual void onBufferReceived(int streamId,
                                  const CpuConsumer::LockedBuffer& buf) = 0;
    // A new metadata buffer has been received.
    // -- Ownership of request passes on to the callee,
    //    free with free_camera_metadata.
    virtual void onRequestReceived(camera_metadata* request) = 0;
    /**
      * A new metadata buffer has been received.
      * -- Ownership of request passes on to the callee, free with
      *    free_camera_metadata.
      */
    virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0;
};

class ProCamera : public BnProCameraCallbacks, public IBinder::DeathRecipient
@@ -189,6 +191,9 @@ protected:
    virtual void        onLockStatusChanged(
                                IProCameraCallbacks::LockStatus newLockStatus);

    virtual void        onResultReceived(int32_t frameId,
                                         camera_metadata* result);

    class DeathNotifier: public IBinder::DeathRecipient
    {
    public:
Loading