Merge "Create another thread to handle frames" into rvc-dev
diff --git a/surround_view/service-impl/SurroundView3dSession.cpp b/surround_view/service-impl/SurroundView3dSession.cpp
index 88913af..ed7a16c 100644
--- a/surround_view/service-impl/SurroundView3dSession.cpp
+++ b/surround_view/service-impl/SurroundView3dSession.cpp
@@ -41,6 +41,33 @@
static const int kNumChannels = 4;
static const int kFrameDelayInMilliseconds = 30;
+void SurroundView3dSession::processFrames() {
+ if (mSurroundView->Start3dPipeline()) {
+ LOG(INFO) << "Start3dPipeline succeeded";
+ } else {
+ LOG(ERROR) << "Start3dPipeline failed";
+ return;
+ }
+
+ while(mStreamState == RUNNING) {
+ {
+ unique_lock<mutex> lock(mAccessLock);
+
+ mSignal.wait(lock, [this]() {
+ return framesAvailable;
+ });
+ }
+
+ handleFrames(sequenceId);
+
+ {
+ // Set the boolean to false to receive the next set of frames.
+ unique_lock<mutex> lock(mAccessLock);
+ framesAvailable = false;
+ }
+ }
+}
+
SurroundView3dSession::SurroundView3dSession() :
mStreamState(STOPPED){
mEvsCameraIds = {"0" , "1", "2", "3"};
@@ -86,6 +113,10 @@
generateFrames();
});
+ mProcessThread = thread([this]() {
+ processFrames();
+ });
+
return SvResult::OK;
}
@@ -288,18 +319,7 @@
}
void SurroundView3dSession::generateFrames() {
- if (mSurroundView->Start3dPipeline()) {
- LOG(INFO) << "Start3dPipeline succeeded";
- } else {
- LOG(ERROR) << "Start3dPipeline failed";
- return;
- }
-
- int sequenceId = 0;
-
- // TODO(b/150412555): do not use the setViews for frames generation
- // since there is a discrepancy between the HIDL APIs and core lib APIs.
- array<array<float, 4>, 4> matrix;
+ sequenceId = 0;
while(true) {
{
@@ -355,82 +375,106 @@
}
}
- // TODO(b/150412555): use hard-coded views for now. Change view every
- // frame.
- int recViewId = sequenceId % 16;
- for (int i=0; i<4; i++)
- for (int j=0; j<4; j++) {
- matrix[i][j] = kRecViews[recViewId][i*4+j];
- }
+ LOG(INFO) << "Notify all. SequenceId " << sequenceId << " is ready";
+ framesAvailable = true;
+ mSignal.notify_all();
- if (mSurroundView->Get3dSurroundView(
- mInputPointers, matrix, &mOutputPointer)) {
- LOG(INFO) << "Get3dSurroundView succeeded";
+ // TODO(b/150412555): adding delays explicitly. This delay should be
+ // removed when EVS camera is used.
+ this_thread::sleep_for(chrono::milliseconds(
+ kFrameDelayInMilliseconds));
+
+ sequenceId++;
+ }
+
+ // If we've been asked to stop, send an event to signal the actual end of stream
+ LOG(DEBUG) << "Notify SvEvent::STREAM_STOPPED";
+ mStream->notify(SvEvent::STREAM_STOPPED);
+}
+
+bool SurroundView3dSession::handleFrames(int sequenceId) {
+
+ LOG(INFO) << __FUNCTION__ << "Handling sequenceId " << sequenceId << ".";
+
+ // TODO(b/150412555): do not use the setViews for frames generation
+ // since there is a discrepancy between the HIDL APIs and core lib APIs.
+ array<array<float, 4>, 4> matrix;
+
+ // TODO(b/150412555): use hard-coded views for now. Change view every
+ // frame.
+ int recViewId = sequenceId % 16;
+ for (int i=0; i<4; i++)
+ for (int j=0; j<4; j++) {
+ matrix[i][j] = kRecViews[recViewId][i*4+j];
+ }
+
+ if (mSurroundView->Get3dSurroundView(
+ mInputPointers, matrix, &mOutputPointer)) {
+ LOG(INFO) << "Get3dSurroundView succeeded";
+ } else {
+ LOG(ERROR) << "Get3dSurroundView failed. "
+ << "Using memset to initialize to gray.";
+ memset(mOutputPointer.data_pointer, kGrayColor,
+ mOutputHeight * mOutputWidth * kNumChannels);
+ }
+
+ void* textureDataPtr = nullptr;
+ mSvTexture->lock(GRALLOC_USAGE_SW_WRITE_OFTEN
+ | GRALLOC_USAGE_SW_READ_NEVER,
+ &textureDataPtr);
+ if (!textureDataPtr) {
+ LOG(ERROR) << "Failed to gain write access to GraphicBuffer!";
+ return false;
+ }
+
+ // Note: there is a chance that the stride of the texture is not the
+ // same as the width. For example, when the input frame is 1920 * 1080,
+ // the width is 1080, but the stride is 2048. So we'd better copy the
+ // data line by line, instead of single memcpy.
+ uint8_t* writePtr = static_cast<uint8_t*>(textureDataPtr);
+ uint8_t* readPtr = static_cast<uint8_t*>(mOutputPointer.data_pointer);
+ const int readStride = mOutputWidth * kNumChannels;
+ const int writeStride = mSvTexture->getStride() * kNumChannels;
+ if (readStride == writeStride) {
+ memcpy(writePtr, readPtr, readStride * mSvTexture->getHeight());
+ } else {
+ for (int i=0; i<mSvTexture->getHeight(); i++) {
+ memcpy(writePtr, readPtr, readStride);
+ writePtr = writePtr + writeStride;
+ readPtr = readPtr + readStride;
+ }
+ }
+ LOG(INFO) << "memcpy finished!";
+ mSvTexture->unlock();
+
+ ANativeWindowBuffer* buffer = mSvTexture->getNativeBuffer();
+ LOG(DEBUG) << "ANativeWindowBuffer->handle: " << buffer->handle;
+
+ framesRecord.frames.svBuffers.resize(1);
+ SvBuffer& svBuffer = framesRecord.frames.svBuffers[0];
+ svBuffer.viewId = 0;
+ svBuffer.hardwareBuffer.nativeHandle = buffer->handle;
+ AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<AHardwareBuffer_Desc *>(
+ &svBuffer.hardwareBuffer.description);
+ pDesc->width = mOutputWidth;
+ pDesc->height = mOutputHeight;
+ pDesc->layers = 1;
+ pDesc->usage = GRALLOC_USAGE_HW_TEXTURE;
+ pDesc->stride = mSvTexture->getStride();
+ pDesc->format = HAL_PIXEL_FORMAT_RGBA_8888;
+ framesRecord.frames.timestampNs = elapsedRealtimeNano();
+ framesRecord.frames.sequenceId = sequenceId;
+
+ {
+ scoped_lock<mutex> lock(mAccessLock);
+
+ if (framesRecord.inUse) {
+ LOG(DEBUG) << "Notify SvEvent::FRAME_DROPPED";
+ mStream->notify(SvEvent::FRAME_DROPPED);
} else {
- LOG(ERROR) << "Get3dSurroundView failed. "
- << "Using memset to initialize to gray.";
- memset(mOutputPointer.data_pointer, kGrayColor,
- mOutputHeight * mOutputWidth * kNumChannels);
- }
-
- void* textureDataPtr = nullptr;
- mSvTexture->lock(GRALLOC_USAGE_SW_WRITE_OFTEN
- | GRALLOC_USAGE_SW_READ_NEVER,
- &textureDataPtr);
- if (!textureDataPtr) {
- LOG(ERROR) << "Failed to gain write access to GraphicBuffer!";
- break;
- }
-
- // Note: there is a chance that the stride of the texture is not the
- // same as the width. For example, when the input frame is 1920 * 1080,
- // the width is 1080, but the stride is 2048. So we'd better copy the
- // data line by line, instead of single memcpy.
- uint8_t* writePtr = static_cast<uint8_t*>(textureDataPtr);
- uint8_t* readPtr = static_cast<uint8_t*>(mOutputPointer.data_pointer);
- const int readStride = mOutputWidth * kNumChannels;
- const int writeStride = mSvTexture->getStride() * kNumChannels;
- if (readStride == writeStride) {
- memcpy(writePtr, readPtr, readStride * mSvTexture->getHeight());
- } else {
- for (int i=0; i<mSvTexture->getHeight(); i++) {
- memcpy(writePtr, readPtr, readStride);
- writePtr = writePtr + writeStride;
- readPtr = readPtr + readStride;
- }
- }
- LOG(INFO) << "memcpy finished!";
- mSvTexture->unlock();
-
- ANativeWindowBuffer* buffer = mSvTexture->getNativeBuffer();
- LOG(DEBUG) << "ANativeWindowBuffer->handle: " << buffer->handle;
-
- framesRecord.frames.svBuffers.resize(1);
- SvBuffer& svBuffer = framesRecord.frames.svBuffers[0];
- svBuffer.viewId = 0;
- svBuffer.hardwareBuffer.nativeHandle = buffer->handle;
- AHardwareBuffer_Desc* pDesc =
- reinterpret_cast<AHardwareBuffer_Desc *>(
- &svBuffer.hardwareBuffer.description);
- pDesc->width = mOutputWidth;
- pDesc->height = mOutputHeight;
- pDesc->layers = 1;
- pDesc->usage = GRALLOC_USAGE_HW_TEXTURE;
- pDesc->stride = mSvTexture->getStride();
- pDesc->format = HAL_PIXEL_FORMAT_RGBA_8888;
- framesRecord.frames.timestampNs = elapsedRealtimeNano();
- framesRecord.frames.sequenceId = sequenceId++;
-
- {
- scoped_lock<mutex> lock(mAccessLock);
-
- if (framesRecord.inUse) {
- LOG(DEBUG) << "Notify SvEvent::FRAME_DROPPED";
- mStream->notify(SvEvent::FRAME_DROPPED);
- } else {
- framesRecord.inUse = true;
- mStream->receiveFrames(framesRecord.frames);
- }
+ framesRecord.inUse = true;
+ mStream->receiveFrames(framesRecord.frames);
}
// TODO(b/150412555): adding delays explicitly. This delay should be
@@ -439,9 +483,7 @@
kFrameDelayInMilliseconds));
}
- // If we've been asked to stop, send an event to signal the actual end of stream
- LOG(DEBUG) << "Notify SvEvent::STREAM_STOPPED";
- mStream->notify(SvEvent::STREAM_STOPPED);
+ return true;
}
bool SurroundView3dSession::initialize() {
diff --git a/surround_view/service-impl/SurroundView3dSession.h b/surround_view/service-impl/SurroundView3dSession.h
index 12337b6..ded6406 100644
--- a/surround_view/service-impl/SurroundView3dSession.h
+++ b/surround_view/service-impl/SurroundView3dSession.h
@@ -32,6 +32,8 @@
using ::android::hardware::hidl_vec;
using ::android::sp;
+using std::condition_variable;
+
using namespace android_auto::surround_view;
namespace android {
@@ -62,9 +64,13 @@
projectCameraPointsTo3dSurface_cb _hidl_cb);
private:
- void generateFrames();
bool initialize();
+ void generateFrames();
+ void processFrames();
+
+ bool handleFrames(int sequenceId);
+
enum StreamStateValues {
STOPPED,
RUNNING,
@@ -77,6 +83,13 @@
StreamStateValues mStreamState GUARDED_BY(mAccessLock);
thread mCaptureThread; // The thread we'll use to synthesize frames
+ thread mProcessThread; // The thread we'll use to process frames
+
+ // Used to signal a set of frames is ready
+ condition_variable mSignal GUARDED_BY(mAccessLock);
+ bool framesAvailable GUARDED_BY(mAccessLock);
+
+ int sequenceId;
struct FramesRecord {
SvFramesDesc frames;