aboutsummaryrefslogtreecommitdiffstats
path: root/evs
diff options
context:
space:
mode:
authorChangyeon Jo <changyeon@google.com>2020-03-29 07:50:53 -0700
committerChangyeon Jo <changyeon@google.com>2020-04-02 13:10:40 -0700
commit6e90a3b41bd62b111a6fcba87eaebf4388e1098a (patch)
tree2b9fe0e9b075693b8a0894c9659fff45a04b48de /evs
parentfe92ef3972ff0f54ebb68bfb855b5a3d06c572a5 (diff)
downloadplatform_packages_services_Car-6e90a3b41bd62b111a6fcba87eaebf4388e1098a.tar.gz
platform_packages_services_Car-6e90a3b41bd62b111a6fcba87eaebf4388e1098a.tar.bz2
platform_packages_services_Car-6e90a3b41bd62b111a6fcba87eaebf4388e1098a.zip
Use user-allocated buffers to capture frames
This change implements importExternal() API that allows EVS HAL implementation to import buffers allocated by EVS clients. Bug: 152493110 Test: m -j and run /system/bin/evs_app --test Change-Id: I29e917fce5c353eee8697bd060f6d667706886b3
Diffstat (limited to 'evs')
-rw-r--r--evs/apps/default/ConfigManager.h5
-rw-r--r--evs/apps/default/EvsStateControl.cpp3
-rw-r--r--evs/apps/default/RenderDirectView.cpp9
-rw-r--r--evs/apps/default/RenderDirectView.h4
-rw-r--r--evs/apps/default/StreamHandler.cpp78
-rw-r--r--evs/apps/default/StreamHandler.h8
-rw-r--r--evs/apps/default/VideoTex.cpp9
-rw-r--r--evs/apps/default/VideoTex.h6
-rw-r--r--evs/apps/default/evs_app.cpp5
-rw-r--r--evs/manager/1.1/HalCamera.cpp52
-rw-r--r--evs/manager/1.1/HalCamera.h2
-rw-r--r--evs/manager/1.1/VirtualCamera.cpp28
-rw-r--r--evs/manager/1.1/VirtualCamera.h3
-rw-r--r--evs/sampleDriver/EvsV4lCamera.cpp90
-rw-r--r--evs/sampleDriver/EvsV4lCamera.h5
15 files changed, 284 insertions, 23 deletions
diff --git a/evs/apps/default/ConfigManager.h b/evs/apps/default/ConfigManager.h
index b3d283e33..6acd83dbf 100644
--- a/evs/apps/default/ConfigManager.h
+++ b/evs/apps/default/ConfigManager.h
@@ -89,6 +89,8 @@ public:
}
const std::vector<DisplayInfo>& getDisplays() const { return mDisplays; };
const DisplayInfo& getActiveDisplay() const { return mDisplays[mActiveDisplayId]; };
+ void useExternalMemory(bool flag) { mUseExternalMemory = flag; }
+ bool getUseExternalMemory() const { return mUseExternalMemory; }
private:
// Camera information
@@ -98,6 +100,9 @@ private:
std::vector<DisplayInfo> mDisplays;
int mActiveDisplayId;
+ // Memory management
+ bool mUseExternalMemory;
+
// Car body information (assumes front wheel steering and origin at center of rear axel)
// Note that units aren't specified and don't matter as long as all length units are consistent
// within the JSON file from which we parse. That is, if everything is in meters, that's fine.
diff --git a/evs/apps/default/EvsStateControl.cpp b/evs/apps/default/EvsStateControl.cpp
index b96355102..e45fe2fa4 100644
--- a/evs/apps/default/EvsStateControl.cpp
+++ b/evs/apps/default/EvsStateControl.cpp
@@ -303,7 +303,8 @@ bool EvsStateControl::configureEvsPipeline(State desiredState) {
if (mCameraList[desiredState].size() == 1) {
// We have a camera assigned to this state for direct view.
mDesiredRenderer = std::make_unique<RenderDirectView>(mEvs,
- mCameraDescList[desiredState][0]);
+ mCameraDescList[desiredState][0],
+ mConfig);
if (!mDesiredRenderer) {
LOG(ERROR) << "Failed to construct direct renderer. Skipping state change.";
return false;
diff --git a/evs/apps/default/RenderDirectView.cpp b/evs/apps/default/RenderDirectView.cpp
index 4a8db7035..293852168 100644
--- a/evs/apps/default/RenderDirectView.cpp
+++ b/evs/apps/default/RenderDirectView.cpp
@@ -42,9 +42,11 @@ const size_t kStreamCfgSz = sizeof(RawStreamConfig);
RenderDirectView::RenderDirectView(sp<IEvsEnumerator> enumerator,
- const CameraDesc& camDesc) :
+ const CameraDesc& camDesc,
+ const ConfigManager& config) :
mEnumerator(enumerator),
- mCameraDesc(camDesc) {
+ mCameraDesc(camDesc),
+ mConfig(config) {
/* Nothing to do */
}
@@ -113,7 +115,8 @@ bool RenderDirectView::activate() {
mTexture.reset(createVideoTexture(mEnumerator,
mCameraDesc.v1.cameraId.c_str(),
foundCfg ? std::move(targetCfg) : nullptr,
- sDisplay));
+ sDisplay,
+ mConfig.getUseExternalMemory()));
if (!mTexture) {
LOG(ERROR) << "Failed to set up video texture for " << mCameraDesc.v1.cameraId;
// TODO: For production use, we may actually want to fail in this case, but not yet...
diff --git a/evs/apps/default/RenderDirectView.h b/evs/apps/default/RenderDirectView.h
index 3514e05b8..65a94e2fd 100644
--- a/evs/apps/default/RenderDirectView.h
+++ b/evs/apps/default/RenderDirectView.h
@@ -35,7 +35,8 @@ using ::android::hardware::camera::device::V3_2::Stream;
class RenderDirectView: public RenderBase {
public:
RenderDirectView(sp<IEvsEnumerator> enumerator,
- const CameraDesc& camDesc);
+ const CameraDesc& camDesc,
+ const ConfigManager& config);
virtual bool activate() override;
virtual void deactivate() override;
@@ -46,6 +47,7 @@ protected:
sp<IEvsEnumerator> mEnumerator;
ConfigManager::CameraInfo mCameraInfo;
CameraDesc mCameraDesc;
+ const ConfigManager& mConfig;
std::unique_ptr<VideoTex> mTexture;
diff --git a/evs/apps/default/StreamHandler.cpp b/evs/apps/default/StreamHandler.cpp
index 328f4546b..b1cfd1fa5 100644
--- a/evs/apps/default/StreamHandler.cpp
+++ b/evs/apps/default/StreamHandler.cpp
@@ -21,16 +21,73 @@
#include <android-base/logging.h>
#include <cutils/native_handle.h>
+#include <ui/GraphicBufferAllocator.h>
using ::android::hardware::automotive::evs::V1_0::EvsResult;
-StreamHandler::StreamHandler(android::sp <IEvsCamera> pCamera) :
- mCamera(pCamera)
-{
- // We rely on the camera having at least two buffers available since we'll hold one and
- // expect the camera to be able to capture a new image in the background.
- pCamera->setMaxFramesInFlight(2);
+buffer_handle_t memHandle = nullptr;
+StreamHandler::StreamHandler(android::sp <IEvsCamera> pCamera,
+ uint32_t numBuffers,
+ bool useOwnBuffers,
+ int32_t width,
+ int32_t height)
+ : mCamera(pCamera),
+ mUseOwnBuffers(useOwnBuffers) {
+ if (!useOwnBuffers) {
+ // We rely on the camera having at least two buffers available since we'll hold one and
+ // expect the camera to be able to capture a new image in the background.
+ pCamera->setMaxFramesInFlight(numBuffers);
+ } else {
+ mOwnBuffers.resize(numBuffers);
+
+ // Acquire the graphics buffer allocator
+ android::GraphicBufferAllocator &alloc(android::GraphicBufferAllocator::get());
+ const auto usage = GRALLOC_USAGE_HW_TEXTURE |
+ GRALLOC_USAGE_SW_READ_RARELY |
+ GRALLOC_USAGE_SW_WRITE_OFTEN;
+ const auto format = HAL_PIXEL_FORMAT_RGBA_8888;
+ for (auto i = 0; i < numBuffers; ++i) {
+ unsigned pixelsPerLine;
+ android::status_t result = alloc.allocate(width,
+ height,
+ format,
+ 1,
+ usage,
+ &memHandle,
+ &pixelsPerLine,
+ 0,
+ "EvsApp");
+ if (result != android::NO_ERROR) {
+ LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
+ } else {
+ BufferDesc_1_1 buf;
+ AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<AHardwareBuffer_Desc *>(&buf.buffer.description);
+ pDesc->width = 640;
+ pDesc->height = 360;
+ pDesc->layers = 1;
+ pDesc->format = HAL_PIXEL_FORMAT_RGBA_8888;
+ pDesc->usage = GRALLOC_USAGE_HW_TEXTURE |
+ GRALLOC_USAGE_SW_READ_RARELY |
+ GRALLOC_USAGE_SW_WRITE_OFTEN;
+ pDesc->stride = pixelsPerLine;
+ buf.buffer.nativeHandle = memHandle;
+ buf.bufferId = i; // Unique number to identify this buffer
+ mOwnBuffers[i] = buf;
+ }
+ }
+
+ int delta = 0;
+ EvsResult result = EvsResult::OK;
+ pCamera->importExternalBuffers(mOwnBuffers,
+ [&](auto _result, auto _delta) {
+ result = _result;
+ delta = _delta;
+ });
+
+ LOG(INFO) << delta << " buffers are imported by EVS.";
+ }
}
@@ -42,6 +99,15 @@ void StreamHandler::shutdown()
// At this point, the receiver thread is no longer running, so we can safely drop
// our remote object references so they can be freed
mCamera = nullptr;
+
+ if (mUseOwnBuffers) {
+ android::GraphicBufferAllocator &alloc(android::GraphicBufferAllocator::get());
+ for (auto& b : mOwnBuffers) {
+ alloc.free(b.buffer.nativeHandle);
+ }
+
+ mOwnBuffers.resize(0);
+ }
}
diff --git a/evs/apps/default/StreamHandler.h b/evs/apps/default/StreamHandler.h
index cb7a288e9..f877c78af 100644
--- a/evs/apps/default/StreamHandler.h
+++ b/evs/apps/default/StreamHandler.h
@@ -48,7 +48,11 @@ class StreamHandler : public IEvsCameraStream {
public:
virtual ~StreamHandler() { shutdown(); };
- StreamHandler(android::sp <IEvsCamera> pCamera);
+ StreamHandler(android::sp <IEvsCamera> pCamera,
+ uint32_t numBuffers = 2,
+ bool useOwnBuffers = false,
+ int32_t width = 640,
+ int32_t height = 360);
void shutdown();
bool startStream();
@@ -83,6 +87,8 @@ private:
BufferDesc mBuffers[2];
int mHeldBuffer = -1; // Index of the one currently held by the client
int mReadyBuffer = -1; // Index of the newest available buffer
+ hidl_vec<BufferDesc_1_1> mOwnBuffers;
+ bool mUseOwnBuffers;
};
diff --git a/evs/apps/default/VideoTex.cpp b/evs/apps/default/VideoTex.cpp
index c9fc8955f..94e734a74 100644
--- a/evs/apps/default/VideoTex.cpp
+++ b/evs/apps/default/VideoTex.cpp
@@ -136,7 +136,8 @@ bool VideoTex::refresh() {
VideoTex* createVideoTexture(sp<IEvsEnumerator> pEnum,
const char* evsCameraId,
std::unique_ptr<Stream> streamCfg,
- EGLDisplay glDisplay) {
+ EGLDisplay glDisplay,
+ bool useExternalMemory) {
// Set up the camera to feed this texture
sp<IEvsCamera> pCamera = nullptr;
if (streamCfg != nullptr) {
@@ -153,7 +154,11 @@ VideoTex* createVideoTexture(sp<IEvsEnumerator> pEnum,
}
// Initialize the stream that will help us update this texture's contents
- sp<StreamHandler> pStreamHandler = new StreamHandler(pCamera);
+ sp<StreamHandler> pStreamHandler = new StreamHandler(pCamera,
+ 2, // number of buffers
+ useExternalMemory,
+ streamCfg->width,
+ streamCfg->height);
if (pStreamHandler.get() == nullptr) {
LOG(ERROR) << "Failed to allocate FrameHandler";
return nullptr;
diff --git a/evs/apps/default/VideoTex.h b/evs/apps/default/VideoTex.h
index 00e9faa8e..d884faadc 100644
--- a/evs/apps/default/VideoTex.h
+++ b/evs/apps/default/VideoTex.h
@@ -37,7 +37,8 @@ class VideoTex: public TexWrapper {
friend VideoTex* createVideoTexture(sp<IEvsEnumerator> pEnum,
const char *evsCameraId,
std::unique_ptr<Stream> streamCfg,
- EGLDisplay glDisplay);
+ EGLDisplay glDisplay,
+ bool useExternalMemory);
public:
VideoTex() = delete;
@@ -64,6 +65,7 @@ private:
VideoTex* createVideoTexture(sp<IEvsEnumerator> pEnum,
const char * deviceName,
std::unique_ptr<Stream> streamCfg,
- EGLDisplay glDisplay);
+ EGLDisplay glDisplay,
+ bool useExternalMemory = false);
#endif // VIDEOTEX_H
diff --git a/evs/apps/default/evs_app.cpp b/evs/apps/default/evs_app.cpp
index 65519c7c2..a968990d1 100644
--- a/evs/apps/default/evs_app.cpp
+++ b/evs/apps/default/evs_app.cpp
@@ -76,6 +76,7 @@ int main(int argc, char** argv)
bool printHelp = false;
const char* evsServiceName = "default";
int displayId = 1;
+ bool useExternalMemory = false;
for (int i=1; i< argc; i++) {
if (strcmp(argv[i], "--test") == 0) {
useVehicleHal = false;
@@ -87,6 +88,8 @@ int main(int argc, char** argv)
printHelp = true;
} else if (strcmp(argv[i], "--display") == 0) {
displayId = std::stoi(argv[++i]);
+ } else if (strcmp(argv[i], "--extmem") == 0) {
+ useExternalMemory = true;
} else {
printf("Ignoring unrecognized command line arg '%s'\n", argv[i]);
printHelp = true;
@@ -98,6 +101,7 @@ int main(int argc, char** argv)
printf(" --hw Bypass EvsManager by connecting directly to EvsEnumeratorHw\n");
printf(" --mock Connect directly to EvsEnumeratorHw-Mock\n");
printf(" --display Specify the display to use\n");
+ printf(" --extmem Application allocates buffers to capture camera frames\n");
}
// Load our configuration information
@@ -135,6 +139,7 @@ int main(int argc, char** argv)
return 1;
}
config.setActiveDisplayId(displayId);
+ config.useExternalMemory(useExternalMemory);
// Connect to the Vehicle HAL so we can monitor state
sp<IVehicle> pVnet;
diff --git a/evs/manager/1.1/HalCamera.cpp b/evs/manager/1.1/HalCamera.cpp
index 902366edc..fef7e9eb0 100644
--- a/evs/manager/1.1/HalCamera.cpp
+++ b/evs/manager/1.1/HalCamera.cpp
@@ -153,6 +153,58 @@ bool HalCamera::changeFramesInFlight(int delta) {
}
+bool HalCamera::changeFramesInFlight(const hidl_vec<BufferDesc_1_1>& buffers,
+ int* delta) {
+ // Return immediately if a list is empty.
+ if (buffers.size() < 1) {
+ LOG(DEBUG) << "No external buffers to add.";
+ return true;
+ }
+
+ // Walk all our clients and count their currently required frames
+ auto bufferCount = 0;
+ for (auto&& client : mClients) {
+ sp<VirtualCamera> virtCam = client.promote();
+ if (virtCam != nullptr) {
+ bufferCount += virtCam->getAllowedBuffers();
+ }
+ }
+
+ EvsResult status = EvsResult::OK;
+ // Ask the hardware for the resulting buffer count
+ mHwCamera->importExternalBuffers(buffers,
+ [&](auto result, auto added) {
+ status = result;
+ *delta = added;
+ });
+ if (status != EvsResult::OK) {
+ LOG(ERROR) << "Failed to add external capture buffers.";
+ return false;
+ }
+
+ bufferCount += *delta;
+
+ // Update the size of our array of outstanding frame records
+ std::vector<FrameRecord> newRecords;
+ newRecords.reserve(bufferCount);
+
+ // Copy and compact the old records that are still active
+ for (const auto& rec : mFrames) {
+ if (rec.refCount > 0) {
+ newRecords.emplace_back(rec);
+ }
+ }
+
+ if (newRecords.size() > (unsigned)bufferCount) {
+ LOG(WARNING) << "We found more frames in use than requested.";
+ }
+
+ mFrames.swap(newRecords);
+
+ return true;
+}
+
+
UniqueFence HalCamera::requestNewFrame(sp<VirtualCamera> client,
const int64_t lastTimestamp) {
if (!mSyncSupported) {
diff --git a/evs/manager/1.1/HalCamera.h b/evs/manager/1.1/HalCamera.h
index b888add55..970dc1691 100644
--- a/evs/manager/1.1/HalCamera.h
+++ b/evs/manager/1.1/HalCamera.h
@@ -79,6 +79,8 @@ public:
std::string getId() { return mId; }
Stream& getStreamConfig() { return mStreamConfig; }
bool changeFramesInFlight(int delta);
+ bool changeFramesInFlight(const hardware::hidl_vec<BufferDesc_1_1>& buffers,
+ int* delta);
UniqueFence requestNewFrame(sp<VirtualCamera> virtualCamera,
const int64_t timestamp);
diff --git a/evs/manager/1.1/VirtualCamera.cpp b/evs/manager/1.1/VirtualCamera.cpp
index 6e203aab1..e9d7b3f65 100644
--- a/evs/manager/1.1/VirtualCamera.cpp
+++ b/evs/manager/1.1/VirtualCamera.cpp
@@ -865,6 +865,34 @@ Return<void> VirtualCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
}
+Return<void>
+VirtualCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) {
+ if (mHalCamera.size() > 1) {
+ LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
+ return {};
+ }
+
+ auto pHwCamera = mHalCamera.begin()->second.promote();
+ if (pHwCamera == nullptr) {
+ LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
+ return {};
+ }
+
+ int delta = 0;
+ if (!pHwCamera->changeFramesInFlight(buffers, &delta)) {
+ LOG(ERROR) << "Failed to add extenral capture buffers.";
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
+ return {};
+ }
+
+ mFramesAllowed += delta;
+ _hidl_cb(EvsResult::OK, delta);
+ return {};
+}
+
} // namespace implementation
} // namespace V1_1
} // namespace evs
diff --git a/evs/manager/1.1/VirtualCamera.h b/evs/manager/1.1/VirtualCamera.h
index 63744d945..764d6c529 100644
--- a/evs/manager/1.1/VirtualCamera.h
+++ b/evs/manager/1.1/VirtualCamera.h
@@ -105,7 +105,8 @@ public:
const hidl_vec<uint8_t>& opaqueValue) override;
Return<void> getExtendedInfo_1_1(uint32_t opaqueIdentifier,
getExtendedInfo_1_1_cb _hidl_cb) override;
-
+ Return<void> importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) override;
private:
diff --git a/evs/sampleDriver/EvsV4lCamera.cpp b/evs/sampleDriver/EvsV4lCamera.cpp
index eefad2a54..fdb893775 100644
--- a/evs/sampleDriver/EvsV4lCamera.cpp
+++ b/evs/sampleDriver/EvsV4lCamera.cpp
@@ -449,6 +449,84 @@ Return<void> EvsV4lCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
}
+Return<void>
+EvsV4lCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) {
+ LOG(DEBUG) << __FUNCTION__;
+
+ // If we've been displaced by another owner of the camera, then we can't do anything else
+ if (!mVideo.isOpen()) {
+ LOG(WARNING) << "Ignoring a request add external buffers "
+ << "when camera has been lost.";
+ _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, mFramesAllowed);
+ return {};
+ }
+
+ auto numBuffersToAdd = buffers.size();
+ if (numBuffersToAdd < 1) {
+ LOG(DEBUG) << "No buffers to add.";
+ _hidl_cb(EvsResult::OK, mFramesAllowed);
+ return {};
+ }
+
+ {
+ std::scoped_lock<std::mutex> lock(mAccessLock);
+
+ if (numBuffersToAdd > (MAX_BUFFERS_IN_FLIGHT - mFramesAllowed)) {
+ numBuffersToAdd -= (MAX_BUFFERS_IN_FLIGHT - mFramesAllowed);
+ LOG(WARNING) << "Exceed the limit on number of buffers. "
+ << numBuffersToAdd << " buffers will be added only.";
+ }
+
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ const auto before = mFramesAllowed;
+ for (auto i = 0; i < numBuffersToAdd; ++i) {
+ // TODO: reject if external buffer is configured differently.
+ auto& b = buffers[i];
+ const AHardwareBuffer_Desc* pDesc =
+ reinterpret_cast<const AHardwareBuffer_Desc *>(&b.buffer.description);
+
+ // Import a buffer to add
+ buffer_handle_t memHandle = nullptr;
+ status_t result = mapper.importBuffer(b.buffer.nativeHandle,
+ pDesc->width,
+ pDesc->height,
+ 1,
+ pDesc->format,
+ pDesc->usage,
+ pDesc->stride,
+ &memHandle);
+ if (result != android::NO_ERROR || !memHandle) {
+ LOG(WARNING) << "Failed to import a buffer " << b.bufferId;
+ continue;
+ }
+
+ auto stored = false;
+ for (auto&& rec : mBuffers) {
+ if (rec.handle == nullptr) {
+ // Use this existing entry
+ rec.handle = memHandle;
+ rec.inUse = false;
+
+ stored = true;
+ break;
+ }
+ }
+
+ if (!stored) {
+ // Add a BufferRecord wrapping this handle to our set of available buffers
+ mBuffers.emplace_back(memHandle);
+ }
+
+ ++mFramesAllowed;
+ }
+
+ _hidl_cb(EvsResult::OK, mFramesAllowed - before);
+ return {};
+ }
+}
+
+
EvsResult EvsV4lCamera::doneWithFrame_impl(const uint32_t bufferId,
const buffer_handle_t memHandle) {
std::lock_guard <std::mutex> lock(mAccessLock);
@@ -649,7 +727,7 @@ void EvsV4lCamera::forwardFrame(imageBuffer* pV4lBuff, void* pData) {
}
if (!readyForFrame) {
- // We need to return the vide buffer so it can capture a new frame
+ // We need to return the video buffer so it can capture a new frame
mVideo.markFrameConsumed();
} else {
// Assemble the buffer description we'll transmit below
@@ -675,10 +753,11 @@ void EvsV4lCamera::forwardFrame(imageBuffer* pV4lBuff, void* pData) {
// causes SEGV_MAPPER.
void *targetPixels = nullptr;
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
- status_t result = mapper.lock(bufDesc_1_1.buffer.nativeHandle,
- GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
- android::Rect(pDesc->width, pDesc->height),
- (void **)&targetPixels);
+ status_t result =
+ mapper.lock(bufDesc_1_1.buffer.nativeHandle,
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
+ android::Rect(pDesc->width, pDesc->height),
+ (void **)&targetPixels);
// If we failed to lock the pixel buffer, we're about to crash, but log it first
if (!targetPixels) {
@@ -740,6 +819,7 @@ void EvsV4lCamera::forwardFrame(imageBuffer* pV4lBuff, void* pData) {
// Since we didn't actually deliver it, mark the frame as available
std::lock_guard<std::mutex> lock(mAccessLock);
mBuffers[idx].inUse = false;
+
mFramesInUse--;
}
}
diff --git a/evs/sampleDriver/EvsV4lCamera.h b/evs/sampleDriver/EvsV4lCamera.h
index 3dc9f064b..c5b15a953 100644
--- a/evs/sampleDriver/EvsV4lCamera.h
+++ b/evs/sampleDriver/EvsV4lCamera.h
@@ -24,8 +24,9 @@
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
#include <ui/GraphicBuffer.h>
-#include <thread>
#include <functional>
+#include <thread>
+#include <set>
#include "VideoCapture.h"
#include "ConfigManager.h"
@@ -85,6 +86,8 @@ public:
const hidl_vec<uint8_t>& opaqueValue) override;
Return<void> getExtendedInfo_1_1(uint32_t opaqueIdentifier,
getExtendedInfo_1_1_cb _hidl_cb) override;
+ Return<void> importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
+ importExternalBuffers_cb _hidl_cb) override;
static sp<EvsV4lCamera> Create(const char *deviceName);
static sp<EvsV4lCamera> Create(const char *deviceName,