Compare commits
No commits in common. "ed44167c0e99d4aed9f2142be6a3347b4e015f4b" and "2968d73f9ff1f00c10876b8af1b0c384747dbbf2" have entirely different histories.
ed44167c0e
...
2968d73f9f
29
image.h
29
image.h
|
@ -6,39 +6,16 @@
|
||||||
|
|
||||||
class Image
|
class Image
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
ssize_t bufferSize = -1;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum {
|
|
||||||
FORMAT_RGB,
|
|
||||||
FORMAT_JPEG,
|
|
||||||
FORMAT_YUYV
|
|
||||||
} typedef format_t;
|
|
||||||
|
|
||||||
std::shared_ptr<unsigned char> data = nullptr;
|
std::shared_ptr<unsigned char> data = nullptr;
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint8_t channels;
|
uint8_t channels;
|
||||||
format_t format = FORMAT_RGB;
|
const uint32_t size()
|
||||||
|
|
||||||
const size_t size() const
|
|
||||||
{
|
{
|
||||||
return bufferSize < 0 ? width*height*channels : bufferSize;
|
return width*height*channels;
|
||||||
}
|
}
|
||||||
void setSize(size_t size)
|
void save(const char* filename)
|
||||||
{
|
|
||||||
bufferSize = size;
|
|
||||||
}
|
|
||||||
void setBuffer(std::shared_ptr<unsigned char> buffer, size_t size, format_t inFormat = FORMAT_RGB)
|
|
||||||
{
|
|
||||||
data = buffer;
|
|
||||||
bufferSize = size;
|
|
||||||
format = inFormat;
|
|
||||||
}
|
|
||||||
void save(const char* filename) const
|
|
||||||
{
|
{
|
||||||
std::ofstream outfile(filename);
|
std::ofstream outfile(filename);
|
||||||
outfile.write((char *) data.get(), size());
|
outfile.write((char *) data.get(), size());
|
||||||
|
|
|
@ -13,8 +13,7 @@ Image decompressJpegImage(const unsigned char* buffer, size_t size)
|
||||||
jpeg_create_decompress( &info ); //fills info structure
|
jpeg_create_decompress( &info ); //fills info structure
|
||||||
|
|
||||||
jpeg_mem_src(&info, buffer, size);
|
jpeg_mem_src(&info, buffer, size);
|
||||||
if(jpeg_read_header(&info, true) != JPEG_HEADER_OK)
|
jpeg_read_header( &info, true );
|
||||||
std::cerr<<"Could not read jpeg header";
|
|
||||||
|
|
||||||
jpeg_start_decompress( &info );
|
jpeg_start_decompress( &info );
|
||||||
|
|
||||||
|
@ -25,7 +24,7 @@ Image decompressJpegImage(const unsigned char* buffer, size_t size)
|
||||||
image.channels = info.num_components; // 3 = RGB, 4 = RGBA
|
image.channels = info.num_components; // 3 = RGB, 4 = RGBA
|
||||||
|
|
||||||
// read RGB(A) scanlines one at a time into jdata[]
|
// read RGB(A) scanlines one at a time into jdata[]
|
||||||
image.data = std::shared_ptr<unsigned char>(new unsigned char[image.size()], std::default_delete<unsigned char[]>());
|
image.data = std::shared_ptr<unsigned char>(new unsigned char[image.size()]);
|
||||||
unsigned char* rowptr;
|
unsigned char* rowptr;
|
||||||
while(info.output_scanline < image.height)
|
while(info.output_scanline < image.height)
|
||||||
{
|
{
|
||||||
|
@ -58,7 +57,7 @@ Image decompressJpegImage(FILE *file)
|
||||||
image.channels = info.num_components; // 3 = RGB, 4 = RGBA
|
image.channels = info.num_components; // 3 = RGB, 4 = RGBA
|
||||||
|
|
||||||
// read RGB(A) scanlines one at a time into jdata[]
|
// read RGB(A) scanlines one at a time into jdata[]
|
||||||
image.data = std::shared_ptr<unsigned char>(new unsigned char[image.size()], std::default_delete<unsigned char[]>());
|
image.data = std::shared_ptr<unsigned char>(new unsigned char[image.size()]);
|
||||||
unsigned char* rowptr;
|
unsigned char* rowptr;
|
||||||
while ( info.output_scanline < image.height )
|
while ( info.output_scanline < image.height )
|
||||||
{
|
{
|
||||||
|
|
14
main.cpp
14
main.cpp
|
@ -41,16 +41,12 @@ int main(int argc, char* argv[])
|
||||||
Config config;
|
Config config;
|
||||||
argp_parse(&argp, argc, argv, 0, 0, &config);
|
argp_parse(&argp, argc, argv, 0, 0, &config);
|
||||||
|
|
||||||
bool passthough = config.mjpeg && config.overlay.empty();
|
|
||||||
|
|
||||||
std::cout<<"UVOS webcam sender v0.1\n";
|
std::cout<<"UVOS webcam sender v0.1\n";
|
||||||
|
|
||||||
Webcam webcam(config.device, config.Xres, config.Yres, config.mjpeg, passthough);
|
Webcam webcam(config.device, config.Xres, config.Yres);
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss<<"nc "<<config.url<<' '<<config.port<<'\n';
|
ss<<"nc "<<config.url<<' '<<config.port;
|
||||||
|
|
||||||
std::cout<<"using "<<ss.str();
|
|
||||||
|
|
||||||
FILE* netcat = popen(ss.str().c_str(), "w");
|
FILE* netcat = popen(ss.str().c_str(), "w");
|
||||||
|
|
||||||
|
@ -58,11 +54,8 @@ int main(int argc, char* argv[])
|
||||||
if(!config.overlay.empty())
|
if(!config.overlay.empty())
|
||||||
{
|
{
|
||||||
if(!overlay.open(config.overlay.c_str(), config.Xres, config.Yres, 3))
|
if(!overlay.open(config.overlay.c_str(), config.Xres, config.Yres, 3))
|
||||||
{
|
|
||||||
std::cout<<"Unable to open "<<config.overlay<<'\n';
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while (!ferror(netcat))
|
while (!ferror(netcat))
|
||||||
{
|
{
|
||||||
|
@ -70,10 +63,7 @@ int main(int argc, char* argv[])
|
||||||
Image frame = webcam.frame(10);
|
Image frame = webcam.frame(10);
|
||||||
if(!config.overlay.empty())
|
if(!config.overlay.empty())
|
||||||
overlayImage(frame, overlay);
|
overlayImage(frame, overlay);
|
||||||
if(!passthough)
|
|
||||||
compressJpegImage(netcat, &frame);
|
compressJpegImage(netcat, &frame);
|
||||||
else
|
|
||||||
fwrite(frame.data.get(), frame.size(), 1, netcat);
|
|
||||||
fflush(netcat);
|
fflush(netcat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,6 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
|
||||||
break;
|
break;
|
||||||
case 'y':
|
case 'y':
|
||||||
config->Yres = std::stoi(arg);
|
config->Yres = std::stoi(arg);
|
||||||
break;
|
|
||||||
case 'o':
|
case 'o':
|
||||||
config->overlay = arg;
|
config->overlay = arg;
|
||||||
break;
|
break;
|
||||||
|
|
37
webcam.cpp
37
webcam.cpp
|
@ -85,12 +85,11 @@ static void v4lconvert_yuyv_to_rgb24(const unsigned char *src,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Webcam::Webcam(const string& device, int width, int height, bool mjpeg, bool passthrough) :
|
Webcam::Webcam(const string& device, int width, int height, bool mjpeg) :
|
||||||
device(device),
|
device(device),
|
||||||
xres(width),
|
xres(width),
|
||||||
yres(height),
|
yres(height),
|
||||||
passthrough_format(passthrough),
|
format(mjpeg ? V4L2_PIX_FMT_JPEG : V4L2_PIX_FMT_YUYV)
|
||||||
format(mjpeg ? V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_YUYV)
|
|
||||||
{
|
{
|
||||||
open_device();
|
open_device();
|
||||||
init_device();
|
init_device();
|
||||||
|
@ -100,7 +99,7 @@ Webcam::Webcam(const string& device, int width, int height, bool mjpeg, bool pas
|
||||||
rgb_frame.width = xres;
|
rgb_frame.width = xres;
|
||||||
rgb_frame.height = yres;
|
rgb_frame.height = yres;
|
||||||
rgb_frame.channels = 3;
|
rgb_frame.channels = 3;
|
||||||
rgb_frame.data = std::shared_ptr<unsigned char>(new unsigned char[rgb_frame.size()], std::default_delete<unsigned char[]>());
|
rgb_frame.data = std::shared_ptr<unsigned char>(new unsigned char[rgb_frame.size()]);
|
||||||
|
|
||||||
start_capturing();
|
start_capturing();
|
||||||
}
|
}
|
||||||
|
@ -139,8 +138,6 @@ const Image& Webcam::frame(int timeout)
|
||||||
}
|
}
|
||||||
int idx = read_frame();
|
int idx = read_frame();
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
if(!passthrough_format)
|
|
||||||
{
|
|
||||||
if (format == V4L2_PIX_FMT_YUYV)
|
if (format == V4L2_PIX_FMT_YUYV)
|
||||||
{
|
{
|
||||||
v4lconvert_yuyv_to_rgb24((unsigned char *) buffers[idx].data,
|
v4lconvert_yuyv_to_rgb24((unsigned char *) buffers[idx].data,
|
||||||
|
@ -149,33 +146,10 @@ const Image& Webcam::frame(int timeout)
|
||||||
yres,
|
yres,
|
||||||
stride);
|
stride);
|
||||||
}
|
}
|
||||||
else if(format == V4L2_PIX_FMT_MJPEG)
|
else if(format == V4L2_PIX_FMT_JPEG)
|
||||||
{
|
{
|
||||||
rgb_frame = decompressJpegImage((unsigned char *) buffers[idx].data, buffers[idx].size);
|
rgb_frame = decompressJpegImage((unsigned char *) buffers[idx].data, buffers[idx].size);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(format == V4L2_PIX_FMT_YUYV)
|
|
||||||
{
|
|
||||||
rgb_frame.setBuffer(std::shared_ptr<unsigned char>(new unsigned char[buffers[idx].size], std::default_delete<unsigned char[]>()),
|
|
||||||
buffers[idx].size, Image::FORMAT_YUYV);
|
|
||||||
}
|
|
||||||
else if(format == V4L2_PIX_FMT_MJPEG)
|
|
||||||
{
|
|
||||||
rgb_frame.setBuffer(std::shared_ptr<unsigned char>(new unsigned char[buffers[idx].size], std::default_delete<unsigned char[]>()),
|
|
||||||
buffers[idx].size, Image::FORMAT_RGB);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
memcpy(rgb_frame.data.get(), buffers[idx].data, buffers[idx].size);
|
|
||||||
}
|
|
||||||
return rgb_frame;
|
return rgb_frame;
|
||||||
}
|
}
|
||||||
/* EAGAIN - continue select loop. */
|
/* EAGAIN - continue select loop. */
|
||||||
|
@ -362,8 +336,7 @@ void Webcam::init_device(void)
|
||||||
{
|
{
|
||||||
// note that libv4l2 (look for 'v4l-utils') provides helpers
|
// note that libv4l2 (look for 'v4l-utils') provides helpers
|
||||||
// to manage conversions
|
// to manage conversions
|
||||||
throw runtime_error("Webcam does not support the requested format. Support for more formats need to be added! video format is "
|
throw runtime_error("Webcam does not support the requested format. Support for more formats need to be added!");
|
||||||
+ std::to_string(fmt.fmt.pix.pixelformat));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note VIDIOC_S_FMT may change width and height. */
|
/* Note VIDIOC_S_FMT may change width and height. */
|
||||||
|
|
3
webcam.h
3
webcam.h
|
@ -18,7 +18,7 @@ class Webcam {
|
||||||
public:
|
public:
|
||||||
Webcam(const std::string& device = "/dev/video0",
|
Webcam(const std::string& device = "/dev/video0",
|
||||||
int width = 640,
|
int width = 640,
|
||||||
int height = 480, bool mjpeg = false, bool passthrough = false);
|
int height = 480, bool mjpeg = false);
|
||||||
|
|
||||||
~Webcam();
|
~Webcam();
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ private:
|
||||||
size_t stride;
|
size_t stride;
|
||||||
|
|
||||||
bool force_format = true;
|
bool force_format = true;
|
||||||
bool passthrough_format;
|
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue