Skip to content

Commit

Permalink
Updated linux frame buffer enumeration
Browse files Browse the repository at this point in the history
  • Loading branch information
trcwm committed Jul 13, 2017
2 parents 203bb32 + 8f9f180 commit 68787c2
Show file tree
Hide file tree
Showing 16 changed files with 878 additions and 167 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ ELSEIF(APPLE)
target_link_libraries(openpnp-capture
"-framework AVFoundation"
"-framework Foundation"
"-framework CoreMedia"
)

# add mac specific test application
Expand Down
68 changes: 64 additions & 4 deletions common/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,47 @@ uint32_t Context::getDeviceCount() const
}


int32_t Context::openStream(CapDeviceID id)
int32_t Context::getNumFormats(CapDeviceID index) const
{
if (index >= m_devices.size())
{
LOG(LOG_ERR,"Device with ID %d not found", index);
return -1; // no such device ID!
}
if (m_devices[index] == nullptr)
{
LOG(LOG_ERR,"Internal device pointer is NULL");
return -1; // device pointer is NULL!
}
return m_devices[index]->m_formats.size();
}


bool Context::getFormatInfo(CapDeviceID index, CapFormatID formatID, CapFormatInfo *info) const
{
if (index >= m_devices.size())
{
LOG(LOG_ERR,"Device with ID %d not found", index);
return false; // no such device ID!
}
if (m_devices[index] == nullptr)
{
LOG(LOG_ERR,"Internal device pointer is NULL");
return false; // device pointer is NULL!
}
if (formatID < m_devices[index]->m_formats.size())
{
*info = m_devices[index]->m_formats[formatID];
}
else
{
LOG(LOG_ERR,"Invalid format ID (got %d but max ID is %d)\n", formatID, m_devices[index]->m_formats.size());
return false; // invalid format ID
}
return true;
}

int32_t Context::openStream(CapDeviceID id, CapFormatID formatID)
{
deviceInfo *device = nullptr;

Expand All @@ -57,15 +97,23 @@ int32_t Context::openStream(CapDeviceID id)
}
else
{
LOG(LOG_ERR, "openStream: No devices found\n", device->m_name.c_str());
LOG(LOG_ERR, "openStream: No devices found\n");
return -1;
}

// lookup desired format
if (formatID >= device->m_formats.size())
{
LOG(LOG_ERR, "openStream: Requested format index out of range\n");
return -1;
}

//Stream *s = new PlatformStream();
Stream *s = createPlatformStream();

if (!s->open(this, device, 0,0,0))
if (!s->open(this, device, device->m_formats[formatID].width,
device->m_formats[formatID].height,
device->m_formats[formatID].fourcc))
{
LOG(LOG_ERR, "Could not open stream for device %s\n", device->m_name.c_str());
return -1;
Expand Down Expand Up @@ -235,4 +283,16 @@ bool Context::getStreamExposureLimits(int32_t streamID, int32_t *min, int32_t *m
Stream* stream = Context::lookupStreamByID(streamID);
if (stream == nullptr) return false;
return stream->getExposureLimits(min, max);
}
}

/** convert a FOURCC uint32_t to human readable form */
std::string fourCCToString(uint32_t fourcc)
{
std::string v;
for(uint32_t i=0; i<4; i++)
{
v += static_cast<char>(fourcc & 0xFF);
fourcc >>= 8;
}
return v;
};
33 changes: 13 additions & 20 deletions common/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ class Context
const char* getDeviceName(CapDeviceID id) const;

/** Return the number of devices found */
uint32_t getDeviceCount() const;
uint32_t getDeviceCount() const;

/** return the number of formats supported by a certain device */
int32_t getNumFormats(CapDeviceID index) const;

/** get the format information from a device. */
bool getFormatInfo(CapDeviceID index, CapFormatID id, CapFormatInfo *info) const;

/** Opens a stream to a device with index/ID id and returns the stream ID.
If an error occurs (device not found), -1 is returned.
Expand All @@ -62,7 +68,7 @@ class Context
Note: for now, only one stream per device is supported but opening more
streams might or might not work.
*/
int32_t openStream(CapDeviceID id);
int32_t openStream(CapDeviceID id, CapFormatID formatID);

/** close the stream to a device */
bool closeStream(int32_t streamID);
Expand Down Expand Up @@ -90,7 +96,8 @@ class Context

protected:
/** Enumerate all capture devices and put their
information into the m_devices array
information (name, buffer formats etc) into
the m_devices array.
Implement this function in a platform-dependent
derived class.
Expand All @@ -110,26 +117,12 @@ class Context
Return true if this was successful */
bool removeStream(int32_t ID);


#if 0
/** Convert a wide character string to an UTF-8 string

Implement this function in a platform-dependent
derived class.
*/
virtual std::string wstringToString(const std::wstring &wstr) = 0;

/** Convert a wide charater string to an UTF-8 string

Implement this function in a platform-dependent
derived class.
*/
virtual std::string wcharPtrToString(const wchar_t *str) = 0;
#endif

std::vector<deviceInfo*> m_devices; ///< list of enumerated devices
std::map<int32_t, Stream*> m_streams; ///< collection of streams
int32_t m_streamCounter; ///< counter to generate stream IDs
};

/** convert a FOURCC uint32_t to human readable form */
std::string fourCCToString(uint32_t fourcc);

#endif
5 changes: 4 additions & 1 deletion common/deviceinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@
#define deviceinfo_h

#include <string>
#include <vector>
#include "openpnp-capture.h"

/** device information struct/object */
class deviceInfo
{
public:
virtual ~deviceInfo() {}

std::string m_name; ///< UTF-8 printable name
std::string m_name; ///< UTF-8 printable name
std::vector<CapFormatInfo> m_formats; ///< available buffer formats
};

#endif
25 changes: 23 additions & 2 deletions common/libmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,38 @@ DLLPUBLIC const char* Cap_getDeviceName(CapContext ctx, CapDeviceID id)
return 0;
}

DLLPUBLIC int32_t Cap_getNumFormats(CapContext ctx, CapDeviceID id)
{
if (ctx != 0)
{
return reinterpret_cast<Context*>(ctx)->getNumFormats(id);
}
return -1;
}

DLLPUBLIC CapResult Cap_getFormatInfo(CapContext ctx, CapDeviceID index, CapFormatID id, CapFormatInfo *info)
{
if (ctx != 0)
{
if (reinterpret_cast<Context*>(ctx)->getFormatInfo(index, id, info))
{
return CAPRESULT_OK;
}
}
return CAPRESULT_ERR;
}

DLLPUBLIC void Cap_setLogLevel(uint32_t level)
{
setLogLevel(level);
}

DLLPUBLIC CapStream Cap_openStream(CapContext ctx, CapDeviceID index, uint32_t width, uint32_t height, uint32_t fourCC)
DLLPUBLIC CapStream Cap_openStream(CapContext ctx, CapDeviceID index, CapFormatID formatID)
{
if (ctx != 0)
{
Context *c = reinterpret_cast<Context*>(ctx);
return c->openStream(index);
return c->openStream(index, formatID);
}
return -1;
}
Expand Down
32 changes: 30 additions & 2 deletions include/openpnp-capture.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ typedef void* CapContext; ///< an opaque pointer to the internal Context*
typedef int32_t CapStream; ///< a stream identifier (normally >=0, <0 for error)
typedef uint32_t CapResult; ///< result defined by CAPRESULT_xxx
typedef uint32_t CapDeviceID; ///< unique device ID
typedef uint32_t CapFormatID; ///< format identifier 0 .. numFormats

struct CapFormatInfo
{
uint32_t width; ///< width in pixels
uint32_t height; ///< height in pixels
uint32_t fourcc; ///< fourcc code (platform dependent)
uint32_t fps; ///< frames per second
uint32_t bpp; ///< bits per pixel
};

#define CAPRESULT_OK 0
#define CAPRESULT_ERR 1
Expand Down Expand Up @@ -75,12 +85,23 @@ DLLPUBLIC uint32_t Cap_getDeviceCount(CapContext ctx);
*/
DLLPUBLIC const char* Cap_getDeviceName(CapContext ctx, CapDeviceID index);

/** return the number of formats supported by a certain device.
returns -1 if device does not exist.
*/
DLLPUBLIC int32_t Cap_getNumFormats(CapContext ctx, CapDeviceID index);

/** get the format information from a device. */
DLLPUBLIC CapResult Cap_getFormatInfo(CapContext ctx, CapDeviceID index, CapFormatID id, CapFormatInfo *info);

/** open a capture stream to a device with specific format requirements
Note: if the device is not capable of the requirements or the device
If the device is not capable of the requirements or the device
does not exits, -1 is returned.
Although the (internal) frame buffer format is set via the fourCC ID,
the frames returned by Cap_captureFrame are always 24-bit RGB.
*/
DLLPUBLIC CapStream Cap_openStream(CapContext ctx, CapDeviceID index, uint32_t width, uint32_t height, uint32_t fourCC);
DLLPUBLIC CapStream Cap_openStream(CapContext ctx, CapDeviceID index, CapFormatID formatID);

/** close a capture stream */
DLLPUBLIC CapResult Cap_closeStream(CapContext ctx, CapStream stream);
Expand All @@ -100,8 +121,15 @@ DLLPUBLIC uint32_t Cap_hasNewFrame(CapContext ctx, CapStream stream);
For debugging purposes */
DLLPUBLIC uint32_t Cap_getStreamFrameCount(CapContext ctx, CapStream stream);



/** Get the exposure min and max in 'camera' units */
DLLPUBLIC CapResult Cap_getExposureLimits(CapContext ctx, CapStream stream, int32_t *min, int32_t *max);

/** Set the exposure in 'camera' units */
DLLPUBLIC CapResult Cap_setExposure(CapContext ctx, CapStream stream, int32_t value);

/** Set enable/disable the automatic exposure */
DLLPUBLIC CapResult Cap_setAutoExposure(CapContext ctx, CapStream stream, uint32_t bOnOff);

DLLPUBLIC void Cap_setLogLevel(uint32_t level);
Expand Down
34 changes: 26 additions & 8 deletions linux/platformcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ bool PlatformContext::enumerateDevices()
LOG(LOG_ERR, "enumerateDevices: Can't get capabilities\n");
continue;
}
else

if ((video_cap.device_caps & V4L2_CAP_VIDEO_CAPTURE) != 0)
{
LOG(LOG_INFO,"Name: '%s'\n", video_cap.card);
LOG(LOG_INFO,"Path: '%s'\n", fname);
Expand Down Expand Up @@ -102,12 +103,6 @@ bool PlatformContext::enumerateDevices()
LOG(LOG_INFO,"async I/O NOT supported\n");
}

//printf("Minimum size:\t%d x %d\n", video_cap.minwidth, video_cap.minheight);
//printf("Maximum size:\t%d x %d\n", video_cap.maxwidth, video_cap.maxheight);
}

if ((video_cap.device_caps & V4L2_CAP_VIDEO_CAPTURE) != 0)
{
platformDeviceInfo* dinfo = new platformDeviceInfo();
dinfo->m_name = std::string((const char*)video_cap.card);
dinfo->m_devicePath = std::string(fname);
Expand All @@ -122,7 +117,6 @@ bool PlatformContext::enumerateDevices()
{
fmtdesc.index = index;

// first we find the pixel format type / fourcc
if (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == -1)
{
tryMore = false;
Expand Down Expand Up @@ -154,3 +148,27 @@ bool PlatformContext::enumerateDevices()
}
return true;
}


bool PlatformContext::queryFrameSize(int fd, uint32_t index, uint32_t pixelformat, uint32_t *width, uint32_t *height)
{
v4l2_frmsizeenum frmSize;
frmSize.index = index;
frmSize.pixel_format = pixelformat;
if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmSize) != -1)
{
if (frmSize.type == V4L2_FRMSIZE_TYPE_DISCRETE)
{
*width = frmSize.discrete.width;
*height = frmSize.discrete.height;
}
else
{
LOG(LOG_WARNING, "queryFrameSize returned non-discrete frame size!\n");
*width = 0;
*height = 0;
}
return true;
}
return false;
}
2 changes: 2 additions & 0 deletions linux/platformcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class PlatformContext : public Context
virtual ~PlatformContext();

protected:
bool queryFrameSize(int fd, uint32_t index, uint32_t pixelformat, uint32_t *width, uint32_t *height);

/** Enumerate V4L capture devices and put their
information into the m_devices array
Expand Down
Loading

0 comments on commit 68787c2

Please sign in to comment.