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

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

ProCamera: Add CpuConsumer asynchronous mode support

Bug: 8290146
Bug: 8291751
Change-Id: I25423a2b8a70ac7169911b1c7b482aa17190fe0f
parent 8fdfbe27
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -241,6 +241,17 @@ status_t ProCamera::createStreamCpu(int width, int height, int format,
                                    int heapCount,
                                    /*out*/
                                    sp<CpuConsumer>* cpuConsumer,
                                    int* streamId) {
    return createStreamCpu(width, height, format, heapCount,
                           /*synchronousMode*/true,
                           cpuConsumer, streamId);
}

status_t ProCamera::createStreamCpu(int width, int height, int format,
                                    int heapCount,
                                    bool synchronousMode,
                                    /*out*/
                                    sp<CpuConsumer>* cpuConsumer,
                                    int* streamId)
{
    ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
@@ -251,7 +262,7 @@ status_t ProCamera::createStreamCpu(int width, int height, int format,
    sp <IProCameraUser> c = mCamera;
    if (c == 0) return NO_INIT;

    sp<CpuConsumer> cc = new CpuConsumer(heapCount);
    sp<CpuConsumer> cc = new CpuConsumer(heapCount, synchronousMode);
    cc->setName(String8("ProCamera::mCpuConsumer"));

    sp<Surface> stc = new Surface(
@@ -272,6 +283,7 @@ status_t ProCamera::createStreamCpu(int width, int height, int format,

    getStreamInfo(*streamId).cpuStream = true;
    getStreamInfo(*streamId).cpuConsumer = cc;
    getStreamInfo(*streamId).synchronousMode = synchronousMode;
    getStreamInfo(*streamId).stc = stc;
    // for lifetime management
    getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
@@ -373,6 +385,13 @@ int ProCamera::dropFrameBuffer(int streamId, int count) {
        return BAD_VALUE;
    }

    if (!si.synchronousMode) {
        ALOGW("%s: No need to drop frames on asynchronous streams,"
              " as asynchronous mode only keeps 1 latest frame around.",
              __FUNCTION__);
        return BAD_VALUE;
    }

    int numDropped = 0;
    for (int i = 0; i < count; ++i) {
        CpuConsumer::LockedBuffer buffer;
+54 −2
Original line number Diff line number Diff line
@@ -1061,7 +1061,7 @@ TEST_F(ProCameraTest, WaitForDualStreamBuffer) {
    EXPECT_OK(mCamera->exclusiveUnlock());
}

TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFrames) {
TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFramesSync) {
    if (HasFatalFailure()) {
        return;
    }
@@ -1071,7 +1071,8 @@ TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFrames) {
    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                  TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &consumer, &streamId));
                  TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
                  /*synchronousMode*/true, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());
@@ -1114,6 +1115,57 @@ TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFrames) {
    EXPECT_OK(mCamera->exclusiveUnlock());
}

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

    const int NUM_REQUESTS = 20 * TEST_CPU_FRAME_COUNT;

    int streamId = -1;
    sp<CpuConsumer> consumer;
    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
                  TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT,
                  /*synchronousMode*/false, &consumer, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());

    uint8_t streams[] = { streamId };
    ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1,
                                                     /*requests*/NUM_REQUESTS));

    // Consume a couple of results
    for (int i = 0; i < NUM_REQUESTS; ++i) {
        int numFrames;
        EXPECT_TRUE((numFrames = mCamera->waitForFrameBuffer(streamId)) > 0);

        dout << "Dropped " << (numFrames - 1) << " frames" << std::endl;

        // Skip the counter ahead, don't try to consume these frames again
        i += numFrames-1;

        // "Consume" the buffer
        CpuConsumer::LockedBuffer buf;
        EXPECT_OK(consumer->lockNextBuffer(&buf));

        dout << "Buffer asynchronously received on streamId = " << streamId <<
                ", dataPtr = " << (void*)buf.data <<
                ", timestamp = " << buf.timestamp << std::endl;

        // Process at 10fps, stream is at 15fps.
        // This means we will definitely fill up the buffer queue with
        // extra buffers and need to drop them.
        usleep(TEST_FRAME_PROCESSING_DELAY_US);

        EXPECT_OK(consumer->unlockBuffer(buf));
    }

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



//TODO: refactor into separate file
+7 −0
Original line number Diff line number Diff line
@@ -201,6 +201,12 @@ public:
                          /*out*/
                          sp<CpuConsumer>* cpuConsumer,
                          int* streamId);
    status_t createStreamCpu(int width, int height, int format,
                          int heapCount,
                          bool synchronousMode,
                          /*out*/
                          sp<CpuConsumer>* cpuConsumer,
                          int* streamId);

    // Create a request object from a template.
    status_t createDefaultRequest(int templateId,
@@ -296,6 +302,7 @@ private:
        int  streamID;
        bool cpuStream;
        sp<CpuConsumer> cpuConsumer;
        bool synchronousMode;
        sp<ProFrameListener> frameAvailableListener;
        sp<Surface> stc;
        int frameReady;