mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-30 11:37:06 +08:00
[video_thread] run debayer filter if set
- and only free img buf if it was actually allocated
This commit is contained in:
@@ -43,7 +43,7 @@ struct video_config_t front_camera = {
|
|||||||
.subdev_name = NULL,
|
.subdev_name = NULL,
|
||||||
.format = V4L2_PIX_FMT_UYVY,
|
.format = V4L2_PIX_FMT_UYVY,
|
||||||
.buf_cnt = 10,
|
.buf_cnt = 10,
|
||||||
.filters = NULL
|
.filters = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct video_config_t bottom_camera = {
|
struct video_config_t bottom_camera = {
|
||||||
@@ -53,7 +53,7 @@ struct video_config_t bottom_camera = {
|
|||||||
.subdev_name = NULL,
|
.subdev_name = NULL,
|
||||||
.format = V4L2_PIX_FMT_UYVY,
|
.format = V4L2_PIX_FMT_UYVY,
|
||||||
.buf_cnt = 10,
|
.buf_cnt = 10,
|
||||||
.filters = NULL
|
.filters = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ struct video_config_t bottom_camera = {
|
|||||||
.subdev_name = NULL,
|
.subdev_name = NULL,
|
||||||
.format = V4L2_PIX_FMT_UYVY,
|
.format = V4L2_PIX_FMT_UYVY,
|
||||||
.buf_cnt = 60,
|
.buf_cnt = 60,
|
||||||
.filters = NULL
|
.filters = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct video_config_t front_camera = {
|
struct video_config_t front_camera = {
|
||||||
@@ -56,7 +56,7 @@ struct video_config_t front_camera = {
|
|||||||
.subdev_name = "/dev/v4l-subdev1",
|
.subdev_name = "/dev/v4l-subdev1",
|
||||||
.format = V4L2_PIX_FMT_SGBRG10,
|
.format = V4L2_PIX_FMT_SGBRG10,
|
||||||
.buf_cnt = 10,
|
.buf_cnt = 10,
|
||||||
.filters = NULL //{DeMosaic, AEC, ABW}
|
.filters = VIDEO_FILTER_DEBAYER
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool_t write_reg(int fd, char *addr_val, uint8_t cnt)
|
static bool_t write_reg(int fd, char *addr_val, uint8_t cnt)
|
||||||
|
|||||||
@@ -62,7 +62,10 @@ void image_create(struct image_t *img, uint16_t width, uint16_t height, enum ima
|
|||||||
*/
|
*/
|
||||||
void image_free(struct image_t *img)
|
void image_free(struct image_t *img)
|
||||||
{
|
{
|
||||||
free(img->buf);
|
if (img->buf != NULL) {
|
||||||
|
free(img->buf);
|
||||||
|
img->buf = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
// Video
|
// Video
|
||||||
#include "lib/v4l/v4l2.h"
|
#include "lib/v4l/v4l2.h"
|
||||||
#include "lib/vision/image.h"
|
#include "lib/vision/image.h"
|
||||||
|
#include "lib/vision/bayern.h"
|
||||||
#include "lib/encoding/jpeg.h"
|
#include "lib/encoding/jpeg.h"
|
||||||
#include "peripherals/video_device.h"
|
#include "peripherals/video_device.h"
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ PRINT_CONFIG_VAR(VIDEO_THREAD_DEVICE_BUFFERS)
|
|||||||
#define VIDEO_THREAD_SUBDEV NULL
|
#define VIDEO_THREAD_SUBDEV NULL
|
||||||
#endif
|
#endif
|
||||||
#ifndef VIDEO_THREAD_FILTERS
|
#ifndef VIDEO_THREAD_FILTERS
|
||||||
#define VIDEO_THREAD_FILTERS NULL
|
#define VIDEO_THREAD_FILTERS 0
|
||||||
#endif
|
#endif
|
||||||
struct video_config_t custom_camera = {
|
struct video_config_t custom_camera = {
|
||||||
.w = VIDEO_THREAD_VIDEO_WIDTH,
|
.w = VIDEO_THREAD_VIDEO_WIDTH,
|
||||||
@@ -102,12 +103,60 @@ struct video_thread_t video_thread = {
|
|||||||
.shot_number = 0
|
.shot_number = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void video_thread_save_shot(struct image_t *img, struct image_t *img_jpeg)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Search for a file where we can write to
|
||||||
|
char save_name[128];
|
||||||
|
for (; video_thread.shot_number < 99999; video_thread.shot_number++) {
|
||||||
|
sprintf(save_name, "%s/img_%05d.jpg", STRINGIFY(VIDEO_THREAD_SHOT_PATH), video_thread.shot_number);
|
||||||
|
// Check if file exists or not
|
||||||
|
if (access(save_name, F_OK) == -1) {
|
||||||
|
|
||||||
|
// Create a high quality image (99% JPEG encoded)
|
||||||
|
jpeg_encode_image(img, img_jpeg, 99, TRUE);
|
||||||
|
|
||||||
|
#if JPEG_WITH_EXIF_HEADER
|
||||||
|
write_exif_jpeg(save_name, img_jpeg->buf, img_jpeg->buf_size, img_jpeg->w, img_jpeg->h);
|
||||||
|
#else
|
||||||
|
FILE *fp = fopen(save_name, "w");
|
||||||
|
if (fp == NULL) {
|
||||||
|
printf("[video_thread-thread] Could not write shot %s.\n", save_name);
|
||||||
|
} else {
|
||||||
|
// Save it to the file and close it
|
||||||
|
fwrite(img_jpeg->buf, sizeof(uint8_t), img_jpeg->buf_size, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We don't need to seek for a next index anymore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles all the video streaming and saving of the image shots
|
* Handles all the video streaming and saving of the image shots
|
||||||
* This is a sepereate thread, so it needs to be thread safe!
|
* This is a sepereate thread, so it needs to be thread safe!
|
||||||
*/
|
*/
|
||||||
static void *video_thread_function(void *data)
|
static void *video_thread_function(void *data)
|
||||||
{
|
{
|
||||||
|
struct video_config_t *vid = (struct video_config_t *)&(VIDEO_THREAD_CAMERA);
|
||||||
|
|
||||||
|
struct image_t img_jpeg;
|
||||||
|
struct image_t img_color;
|
||||||
|
|
||||||
|
// create the images
|
||||||
|
if (vid->filters) {
|
||||||
|
// fixme: don't hardcode size, works for bebop front camera for now
|
||||||
|
#define IMG_FLT_SIZE 272
|
||||||
|
image_create(&img_color, IMG_FLT_SIZE, IMG_FLT_SIZE, IMAGE_YUV422);
|
||||||
|
image_create(&img_jpeg, IMG_FLT_SIZE, IMG_FLT_SIZE, IMAGE_JPEG);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
image_create(&img_jpeg, vid->w, vid->h, IMAGE_JPEG);
|
||||||
|
}
|
||||||
|
|
||||||
// Start the streaming of the V4L2 device
|
// Start the streaming of the V4L2 device
|
||||||
if (!v4l2_start_capture(video_thread.dev)) {
|
if (!v4l2_start_capture(video_thread.dev)) {
|
||||||
@@ -138,48 +187,34 @@ static void *video_thread_function(void *data)
|
|||||||
struct image_t img;
|
struct image_t img;
|
||||||
v4l2_image_get(video_thread.dev, &img);
|
v4l2_image_get(video_thread.dev, &img);
|
||||||
|
|
||||||
|
// pointer to the final image to pass for saving and further processing
|
||||||
|
struct image_t *img_final = &img;
|
||||||
|
|
||||||
|
// run selected filters
|
||||||
|
if (vid->filters) {
|
||||||
|
if (vid->filters & VIDEO_FILTER_DEBAYER) {
|
||||||
|
BayernToYUV(&img, &img_color, 0, 0);
|
||||||
|
}
|
||||||
|
// use color image for further processing
|
||||||
|
img_final = &img_color;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we need to take a shot
|
// Check if we need to take a shot
|
||||||
if (video_thread.take_shot) {
|
if (video_thread.take_shot) {
|
||||||
// Create a high quality image (99% JPEG encoded)
|
video_thread_save_shot(img_final, &img_jpeg);
|
||||||
struct image_t jpeg_hr;
|
|
||||||
image_create(&jpeg_hr, img.w, img.h, IMAGE_JPEG);
|
|
||||||
jpeg_encode_image(&img, &jpeg_hr, 99, TRUE);
|
|
||||||
|
|
||||||
// Search for a file where we can write to
|
|
||||||
char save_name[128];
|
|
||||||
for (; video_thread.shot_number < 99999; video_thread.shot_number++) {
|
|
||||||
sprintf(save_name, "%s/img_%05d.jpg", STRINGIFY(VIDEO_THREAD_SHOT_PATH), video_thread.shot_number);
|
|
||||||
// Check if file exists or not
|
|
||||||
if (access(save_name, F_OK) == -1) {
|
|
||||||
#if JPEG_WITH_EXIF_HEADER
|
|
||||||
write_exif_jpeg(save_name, jpeg_hr.buf, jpeg_hr.buf_size, img.w, img.h);
|
|
||||||
#else
|
|
||||||
FILE *fp = fopen(save_name, "w");
|
|
||||||
if (fp == NULL) {
|
|
||||||
printf("[video_thread-thread] Could not write shot %s.\n", save_name);
|
|
||||||
} else {
|
|
||||||
// Save it to the file and close it
|
|
||||||
fwrite(jpeg_hr.buf, sizeof(uint8_t), jpeg_hr.buf_size, fp);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// We don't need to seek for a next index anymore
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We finished the shot
|
|
||||||
image_free(&jpeg_hr);
|
|
||||||
video_thread.take_shot = FALSE;
|
video_thread.take_shot = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run processing if required
|
// Run processing if required
|
||||||
cv_run(&img);
|
cv_run(img_final);
|
||||||
|
|
||||||
// Free the image
|
// Free the image
|
||||||
v4l2_image_free(video_thread.dev, &img);
|
v4l2_image_free(video_thread.dev, &img);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
image_free(&img_jpeg);
|
||||||
|
image_free(&img_color);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +230,7 @@ void video_thread_init(void)
|
|||||||
// FIXME! add subdev format to config, only needed on bebop front camera so far
|
// FIXME! add subdev format to config, only needed on bebop front camera so far
|
||||||
if (!v4l2_init_subdev(vid->subdev_name, 0, 0, V4L2_MBUS_FMT_SGBRG10_1X10, vid->w, vid->h)) {
|
if (!v4l2_init_subdev(vid->subdev_name, 0, 0, V4L2_MBUS_FMT_SGBRG10_1X10, vid->w, vid->h)) {
|
||||||
printf("[video_thread] Could not initialize the %s subdevice.\n", vid->subdev_name);
|
printf("[video_thread] Could not initialize the %s subdevice.\n", vid->subdev_name);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +238,7 @@ void video_thread_init(void)
|
|||||||
video_thread.dev = v4l2_init(vid->dev_name, vid->w, vid->h, vid->buf_cnt, vid->format);
|
video_thread.dev = v4l2_init(vid->dev_name, vid->w, vid->h, vid->buf_cnt, vid->format);
|
||||||
if (video_thread.dev == NULL) {
|
if (video_thread.dev == NULL) {
|
||||||
printf("[video_thread] Could not initialize the %s V4L2 device.\n", vid->dev_name);
|
printf("[video_thread] Could not initialize the %s V4L2 device.\n", vid->dev_name);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the shot directory
|
// Create the shot directory
|
||||||
@@ -227,7 +262,7 @@ void video_thread_start(void)
|
|||||||
|
|
||||||
// Start the streaming thread
|
// Start the streaming thread
|
||||||
pthread_t tid;
|
pthread_t tid;
|
||||||
if (pthread_create(&tid, NULL, video_thread_function, NULL) != 0) {
|
if (pthread_create(&tid, NULL, video_thread_function, (void*)(&VIDEO_THREAD_CAMERA)) != 0) {
|
||||||
printf("[vievideo] Could not create streaming thread.\n");
|
printf("[vievideo] Could not create streaming thread.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
#include "std.h"
|
#include "std.h"
|
||||||
#include "modules/computer_vision/lib/v4l/v4l2.h"
|
#include "modules/computer_vision/lib/v4l/v4l2.h"
|
||||||
|
|
||||||
|
#define VIDEO_FILTER_DEBAYER 0x01
|
||||||
|
|
||||||
/** V4L2 device settings */
|
/** V4L2 device settings */
|
||||||
struct video_config_t {
|
struct video_config_t {
|
||||||
int w; ///< Width
|
int w; ///< Width
|
||||||
@@ -39,7 +41,7 @@ struct video_config_t {
|
|||||||
char* subdev_name; ///< path to sub device
|
char* subdev_name; ///< path to sub device
|
||||||
uint32_t format; ///< Video format
|
uint32_t format; ///< Video format
|
||||||
uint8_t buf_cnt; ///< Amount of V4L2 video device buffers
|
uint8_t buf_cnt; ///< Amount of V4L2 video device buffers
|
||||||
void* filters; ///< filters to use
|
uint8_t filters; ///< filters to use (bitfield with VIDEO_FILTER_x)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user