diff --git a/conf/airframes/examples/bebop.xml b/conf/airframes/examples/bebop.xml
index 85e7b55a96..8cc00a0023 100644
--- a/conf/airframes/examples/bebop.xml
+++ b/conf/airframes/examples/bebop.xml
@@ -17,9 +17,9 @@
-
-
-
+
+
+
@@ -50,9 +50,6 @@
-
-
-
diff --git a/conf/modules/bebop_front_camera.xml b/conf/modules/bebop_front_camera.xml
deleted file mode 100644
index 894dace458..0000000000
--- a/conf/modules/bebop_front_camera.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
- Video streaming for the Bebop front camera
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- include $(CFG_SHARED)/udp.makefile
-
- BEBOP_FRONT_CAMERA_HOST ?= $(MODEM_HOST)
- BEBOP_FRONT_CAMERA_PORT_OUT ?= 6000
- BEBOP_FRONT_CAMERA_BROADCAST ?= TRUE
-
- BEBOPVIEWVID_CFLAGS = -DBEBOP_FRONT_CAMERA_HOST=$(BEBOP_FRONT_CAMERA_HOST) -DBEBOP_FRONT_CAMERA_PORT_OUT=$(BEBOP_FRONT_CAMERA_PORT_OUT)
- ifeq ($(BEBOP_FRONT_CAMERA_USE_NETCAT),)
- ap.CFLAGS += $(BEBOPVIEWVID_CFLAGS) -DBEBOP_FRONT_CAMERA_BROADCAST=$(BEBOP_FRONT_CAMERA_BROADCAST)
- else
- ap.CFLAGS += $(BEBOPVIEWVID_CFLAGS) -DBEBOP_FRONT_CAMERA_USE_NETCAT
- endif
-
-
-
-
-
-
-
-
diff --git a/sw/airborne/boards/bebop.h b/sw/airborne/boards/bebop.h
index e114d00d2a..4ade6fc957 100644
--- a/sw/airborne/boards/bebop.h
+++ b/sw/airborne/boards/bebop.h
@@ -29,79 +29,6 @@
#include "peripherals/video_device.h"
#include "boards/bebop/mt9f002.h"
-/* define required ouput image size */
-#ifndef MT9F002_OUTPUT_HEIGHT
-#define MT9F002_OUTPUT_HEIGHT 822 // full resolution 3288
-#endif
-
-#ifndef MT9F002_OUTPUT_WIDTH
-#define MT9F002_OUTPUT_WIDTH 1152 // full resolution 4608
-#endif
-
-#ifndef MT9F002_INITIAL_OFFSET_X
-#define MT9F002_INITIAL_OFFSET_X 0. // signed fractional offset from centre of image of original sensor [-0.5,0.5]
-#endif
-
-#ifndef MT9F002_INITIAL_OFFSET_Y
-#define MT9F002_INITIAL_OFFSET_Y 0. // signed fractional offset from centre of image of original sensor [-0.5,0.5]
-#endif
-
-/** Our output is only OUTPUT_SCALER of the pixels we take of the sensor
- * It is programmable in 1/16 steps determined by ScaleFactor = 16/scale_m.
- * Legal values for scale_m are 16 through 128, giving you the ability to scale from
- * 1:1 to 1:8 (with m=128).
- * Example:
- * output_width = 512
- * output_height = 830
- * output_scaler = 0.25
- * We now get an image of 512 by 830 which contains a "compressed version"
- * of what would normally be an image of 2048 by 3320 ISP (4608H x 2592V sensor)
- */
-#ifndef MT9F002_OUTPUT_SCALER
-#define MT9F002_OUTPUT_SCALER 1.
-#endif
-
-/** Exposure of the front camera of the bebop. Experimental values:
- * Outside: 15
- * Inside well lit: 30
- * Inside poorly lit: 60
- */
-#ifndef MT9F002_TARGET_EXPOSURE
-#define MT9F002_TARGET_EXPOSURE 30
-#endif
-
-#ifndef MT9F002_TARGET_FPS
-#define MT9F002_TARGET_FPS 10
-#endif
-
-/* Set the colour balance gains */
-#ifndef MT9F002_GAIN_GREEN1
-#define MT9F002_GAIN_GREEN1 3.0
-#endif
-
-#ifndef MT9F002_GAIN_GREEN2
-#define MT9F002_GAIN_GREEN2 3.0
-#endif
-
-#ifndef MT9F002_GAIN_RED
-#define MT9F002_GAIN_RED 3.0
-#endif
-
-#ifndef MT9F002_GAIN_BLUE
-#define MT9F002_GAIN_BLUE 4.0
-#endif
-
-/* Set pixel increment value to implement subsampling */
-/* Supported values for MT9F002_X_ODD_INC_VAL are 3, 7, 15 and 31 */
-#ifndef MT9F002_X_ODD_INC_VAL
-#define MT9F002_X_ODD_INC_VAL 1
-#endif
-
-/* Supported values for MT9F002_Y_ODD_INC_VAL are 1, 3 and 7 */
-#ifndef MT9F002_Y_ODD_INC_VAL
-#define MT9F002_Y_ODD_INC_VAL 1
-#endif
-
/** uart connected to GPS internally */
#define UART1_DEV /dev/ttyPA1
#define GPS_UBX_ENABLE_NMEA_DATA_MASK 0xff
diff --git a/sw/airborne/boards/bebop/mt9f002.c b/sw/airborne/boards/bebop/mt9f002.c
index f77ca7cd19..ae3f5f7351 100644
--- a/sw/airborne/boards/bebop/mt9f002.c
+++ b/sw/airborne/boards/bebop/mt9f002.c
@@ -29,6 +29,7 @@
#include "mt9f002_regs.h"
#include "math/pprz_algebra_int.h"
#include "boards/bebop.h"
+#include "modules/computer_vision/lib/isp/libisp.h"
#include
#include
@@ -38,10 +39,10 @@
#include
#include
-#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+#define MT9F002_MAX_WIDTH 4608
+#define MT9F002_MAX_HEIGHT 3288
-#define MAX_WIDTH 4608
-#define MAX_HEIGHT 3288
+extern struct libisp_config isp_config;
/* Camera structure */
struct video_config_t front_camera = {
@@ -571,16 +572,16 @@ static void mt9f002_set_blanking(struct mt9f002_t *mt)
/* Calculate minimum line length */
float subsampling_factor = (float)(1 + x_odd_inc) / 2.0f; // See page 52
- uint16_t min_line_length = MAX(min_line_length_pck,
+ uint16_t min_line_length = Max(min_line_length_pck,
mt->scaled_width / subsampling_factor + min_line_blanking_pck); // EQ 9
- min_line_length = MAX(min_line_length,
+ min_line_length = Max(min_line_length,
(mt->scaled_width - 1 + x_odd_inc) / subsampling_factor / 2 + min_line_blanking_pck);
if (mt->interface == MT9F002_MIPI ||
mt->interface == MT9F002_HiSPi) {
- min_line_length = MAX(min_line_length,
+ min_line_length = Max(min_line_length,
((uint16_t)((float)mt->scaled_width * mt->vt_pix_clk / mt->op_pix_clk) / 2) + 0x005E); // 2 lanes, pll clocks
} else {
- min_line_length = MAX(min_line_length,
+ min_line_length = Max(min_line_length,
((uint16_t)((float)mt->scaled_width * mt->vt_pix_clk / mt->op_pix_clk)) + 0x005E); // pll clocks
}
@@ -648,7 +649,6 @@ static void mt9f002_set_blanking(struct mt9f002_t *mt)
}
}
- printf("line: %d, frame %d\n", mt->line_length, mt->frame_length);
/* Actually set the calculated values */
write_reg(mt, MT9F002_LINE_LENGTH_PCK, mt->line_length, 2);
write_reg(mt, MT9F002_FRAME_LENGTH_LINES, mt->frame_length, 2);
@@ -790,33 +790,34 @@ void mt9f002_set_resolution(struct mt9f002_t *mt)
mt->output_scaler = (float)MT9F002_SCALER_N / scaleFactor;
int x_skip_factor = (mt->x_odd_inc + 1) / 2;
int y_skip_factor = (mt->y_odd_inc + 1) / 2;
- mt->scaled_width = mt->output_width * x_skip_factor / mt->output_scaler - mt->x_odd_inc + 1;
- mt->scaled_height = mt->output_height * y_skip_factor / mt->output_scaler - mt->y_odd_inc + 1;
+ mt->scaled_width = mt->output_width * x_skip_factor / mt->output_scaler + mt->x_odd_inc - 1;
+ mt->scaled_height = mt->output_height * y_skip_factor / mt->output_scaler + mt->y_odd_inc - 1;
if (mt->scaled_width % (x_skip_factor * 8) != 0) {
- mt->scaled_width = round(mt->scaled_width / (x_skip_factor * 8)) * (x_skip_factor * 8);
+ mt->scaled_width = floor(mt->scaled_width / (x_skip_factor * 8)) * (x_skip_factor * 8);
printf("[MT9F002] Warning, scaled_width not a multiple of %i, changing to %i\n", 8 * x_skip_factor, mt->scaled_width);
}
if (mt->scaled_height % (y_skip_factor * 8) != 0) {
- mt->scaled_height = round(mt->scaled_height / (y_skip_factor * 8)) * (y_skip_factor * 8);
+ mt->scaled_height = floor(mt->scaled_height / (y_skip_factor * 8)) * (y_skip_factor * 8);
printf("[MT9F002] Warning, scaled_height not a multiple of %i, changing to %i\n", 8 * y_skip_factor, mt->scaled_height);
}
if (mt->output_scaler < 1.0) {
write_reg(mt, MT9F002_SCALING_MODE, 2, 2); // Vertical and horizontal scaling
write_reg(mt, MT9F002_SCALE_M, scaleFactor, 2);
}
- printf("OUTPUT_SIZE: (%i, %i)\tSCALED_SIZE: (%i, %i)\n", mt->output_width, mt->output_height, mt->scaled_width,
+ printf("[MT9F002] OUTPUT_SIZE: (%i, %i)\tSCALED_SIZE: (%i, %i)\n", mt->output_width, mt->output_height,
+ mt->scaled_width,
mt->scaled_height);
/* bound offsets */
- if (mt->offset_x * MAX_WIDTH + mt->scaled_width / 2 > MAX_WIDTH){mt->offset_x = 1 - (float)mt->scaled_width / 2 / MAX_WIDTH;}
- if (-mt->offset_x * MAX_WIDTH > mt->scaled_width){mt->offset_x = -(float)mt->scaled_width/ 2 / MAX_WIDTH;}
+ if (mt->offset_x * MT9F002_MAX_WIDTH + mt->scaled_width / 2 > MT9F002_MAX_WIDTH) {mt->offset_x = 1 - (float)mt->scaled_width / 2 / MT9F002_MAX_WIDTH;}
+ if (-mt->offset_x * MT9F002_MAX_WIDTH > mt->scaled_width) {mt->offset_x = -(float)mt->scaled_width / 2 / MT9F002_MAX_WIDTH;}
- if (mt->offset_y * MAX_HEIGHT + mt->scaled_height / 2 > MAX_HEIGHT){mt->offset_y = 1 - (float)mt->scaled_height/ 2 / MAX_HEIGHT;}
- if (-mt->offset_y * MAX_HEIGHT > mt->scaled_height / 2){mt->offset_y = -(float)mt->scaled_height/ 2 / MAX_HEIGHT;}
+ if (mt->offset_y * MT9F002_MAX_HEIGHT + mt->scaled_height / 2 > MT9F002_MAX_HEIGHT) {mt->offset_y = 1 - (float)mt->scaled_height / 2 / MT9F002_MAX_HEIGHT;}
+ if (-mt->offset_y * MT9F002_MAX_HEIGHT > mt->scaled_height / 2) {mt->offset_y = -(float)mt->scaled_height / 2 / MT9F002_MAX_HEIGHT;}
/* Set position (based on offset and subsample increment) */
- uint16_t start_addr_x = (uint16_t)((MAX_WIDTH - mt->scaled_width) / 2 + mt->offset_x * MAX_WIDTH);
- uint16_t start_addr_y = (uint16_t)((MAX_HEIGHT - mt->scaled_height) / 2 + mt->offset_y * MAX_HEIGHT);
+ uint16_t start_addr_x = (uint16_t)((MT9F002_MAX_WIDTH - mt->scaled_width) / 2 + mt->offset_x * MT9F002_MAX_WIDTH);
+ uint16_t start_addr_y = (uint16_t)((MT9F002_MAX_HEIGHT - mt->scaled_height) / 2 + mt->offset_y * MT9F002_MAX_HEIGHT);
if (start_addr_x < 24) {
start_addr_x = 24;
@@ -837,6 +838,17 @@ void mt9f002_set_resolution(struct mt9f002_t *mt)
uint16_t end_addr_y = start_addr_y + mt->scaled_height - 1;
write_reg(mt, MT9F002_X_ADDR_END, end_addr_x, 2);
write_reg(mt, MT9F002_Y_ADDR_END, end_addr_y, 2);
+
+ // set statistics to correct values
+ isp_config.statistics_bayer.window_x.x_offset = mt->scaled_width - (mt->scaled_width / BAYERSTATS_STATX) / 2;
+ isp_config.statistics_bayer.window_y.y_offset = mt->scaled_height - (mt->scaled_height / BAYERSTATS_STATY) / 2;
+ isp_config.statistics_bayer.window_x.x_width = mt->scaled_width / BAYERSTATS_STATX;
+ isp_config.statistics_bayer.window_y.y_width = mt->scaled_height / BAYERSTATS_STATY;
+
+ isp_config.statistics_yuv.window_pos_x.window_x_end = mt->scaled_width - 1;
+ isp_config.statistics_yuv.window_pos_y.window_y_end = mt->scaled_height - 1;
+ isp_config.statistics_yuv.increments_log2.x_log2_inc = log2(x_skip_factor);
+ isp_config.statistics_yuv.increments_log2.x_log2_inc = log2(y_skip_factor);
}
/**
diff --git a/sw/airborne/boards/bebop/mt9f002.h b/sw/airborne/boards/bebop/mt9f002.h
index b8c1ce0f4f..64fbad1cd7 100644
--- a/sw/airborne/boards/bebop/mt9f002.h
+++ b/sw/airborne/boards/bebop/mt9f002.h
@@ -30,6 +30,79 @@
#include "std.h"
#include "mcu_periph/i2c.h"
+/* define required ouput image size */
+#ifndef MT9F002_OUTPUT_HEIGHT
+#define MT9F002_OUTPUT_HEIGHT 822 // full resolution 3288
+#endif
+
+#ifndef MT9F002_OUTPUT_WIDTH
+#define MT9F002_OUTPUT_WIDTH 1152 // full resolution 4608
+#endif
+
+#ifndef MT9F002_INITIAL_OFFSET_X
+#define MT9F002_INITIAL_OFFSET_X 0. // signed fractional offset from centre of image of original sensor [-0.5,0.5]
+#endif
+
+#ifndef MT9F002_INITIAL_OFFSET_Y
+#define MT9F002_INITIAL_OFFSET_Y 0. // signed fractional offset from centre of image of original sensor [-0.5,0.5]
+#endif
+
+/** Our output is only OUTPUT_SCALER of the pixels we take of the sensor
+ * It is programmable in 1/16 steps determined by ScaleFactor = 16/scale_m.
+ * Legal values for scale_m are 16 through 128, giving you the ability to scale from
+ * 1:1 to 1:8 (with m=128).
+ * Example:
+ * output_width = 512
+ * output_height = 830
+ * output_scaler = 0.25
+ * We now get an image of 512 by 830 which contains a "compressed version"
+ * of what would normally be an image of 2048 by 3320 ISP (4608H x 2592V sensor)
+ */
+#ifndef MT9F002_OUTPUT_SCALER
+#define MT9F002_OUTPUT_SCALER 1.
+#endif
+
+/** Exposure of the front camera of the bebop. Experimental values:
+ * Outside: 15
+ * Inside well lit: 30
+ * Inside poorly lit: 60
+ */
+#ifndef MT9F002_TARGET_EXPOSURE
+#define MT9F002_TARGET_EXPOSURE 30
+#endif
+
+#ifndef MT9F002_TARGET_FPS
+#define MT9F002_TARGET_FPS 15
+#endif
+
+/* Set the colour balance gains */
+#ifndef MT9F002_GAIN_GREEN1
+#define MT9F002_GAIN_GREEN1 3.0
+#endif
+
+#ifndef MT9F002_GAIN_GREEN2
+#define MT9F002_GAIN_GREEN2 3.0
+#endif
+
+#ifndef MT9F002_GAIN_RED
+#define MT9F002_GAIN_RED 3.0
+#endif
+
+#ifndef MT9F002_GAIN_BLUE
+#define MT9F002_GAIN_BLUE 4.0
+#endif
+
+/* Set pixel increment value to implement subsampling */
+/* Supported values for MT9F002_X_ODD_INC_VAL are 3, 7, 15 and 31 */
+#ifndef MT9F002_X_ODD_INC_VAL
+#define MT9F002_X_ODD_INC_VAL 1
+#endif
+
+/* Supported values for MT9F002_Y_ODD_INC_VAL are 1, 3 and 7 */
+#ifndef MT9F002_Y_ODD_INC_VAL
+#define MT9F002_Y_ODD_INC_VAL 1
+#endif
+
/* Interface types for the MT9F002 connection */
enum mt9f002_interface {
MT9F002_MIPI, ///< MIPI type connection
diff --git a/sw/airborne/modules/computer_vision/bebop_front_camera.c b/sw/airborne/modules/computer_vision/bebop_front_camera.c
deleted file mode 100644
index cd4636af8a..0000000000
--- a/sw/airborne/modules/computer_vision/bebop_front_camera.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2012-2014 The Paparazzi Community
- * 2015 Freek van Tienen
- *
- * This file is part of Paparazzi.
- *
- * Paparazzi is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * Paparazzi is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with paparazzi; see the file COPYING. If not, see
- * .
- *
- */
-
-/**
- * @file modules/computer_vision/bebop_front_camera.c
- */
-
-// Own header
-#include "modules/computer_vision/bebop_front_camera.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-// Video
-#include "lib/v4l/v4l2.h"
-#include "lib/vision/image.h"
-#include "lib/vision/bayer.h"
-#include "lib/encoding/jpeg.h"
-#include "lib/encoding/rtp.h"
-#include "udp_socket.h"
-
-// Threaded computer vision
-#include
-
-#define MT9F002_WIDTH 1408
-#define MT9F002_HEIGHT 2112
-#define BEBOP_FRONT_CAMERA_WIDTH 272
-#define BEBOP_FRONT_CAMERA_HEIGHT 272
-
-// The place where the shots are saved (without slash on the end)
-#ifndef BEBOP_FRONT_CAMERA_SHOT_PATH
-#define BEBOP_FRONT_CAMERA_SHOT_PATH /data/ftp/internal_000/images
-#endif
-PRINT_CONFIG_VAR(BEBOP_FRONT_CAMERA_SHOT_PATH)
-
-// Main thread
-static void *bebop_front_camera_thread(void *data);
-static void bebop_front_camera_save_shot(struct image_t *img_color, struct image_t *img_jpeg, struct image_t *raw_img);
-void bebop_front_camera_periodic(void) { }
-
-// Initialize the bebop_front_camera structure with the defaults
-struct bebopfrontcamera_t bebop_front_camera = {
- .is_streaming = FALSE,
- .take_shot = FALSE,
- .shot_number = 0,
- .take_shot = FALSE,
- .shot_number = 0
-};
-
-void bebop_front_camera_take_shot(bool take)
-{
- bebop_front_camera.take_shot = true;
-}
-/**
- * Handles all the video streaming and saving of the image shots
- * This is a sepereate thread, so it needs to be thread safe!
- */
-static void *bebop_front_camera_thread(void *data __attribute__((unused)))
-{
- struct UdpSocket video_sock;
- udp_socket_create(&video_sock, STRINGIFY(BEBOP_FRONT_CAMERA_HOST), BEBOP_FRONT_CAMERA_PORT_OUT, -1,
- BEBOP_FRONT_CAMERA_BROADCAST);
-
- // Create the JPEG encoded image
- struct image_t img_jpeg;
- image_create(&img_jpeg, BEBOP_FRONT_CAMERA_WIDTH, BEBOP_FRONT_CAMERA_HEIGHT, IMAGE_JPEG);
-
- // Create the Color image
- struct image_t img_color;
- image_create(&img_color, BEBOP_FRONT_CAMERA_WIDTH, BEBOP_FRONT_CAMERA_HEIGHT, IMAGE_YUV422);
-
- // Start the streaming of the V4L2 device
- if (!v4l2_start_capture(bebop_front_camera.dev)) {
- printf("[bebop_front_camera-thread] Could not start capture of %s.\n", bebop_front_camera.dev->name);
- return 0;
- }
-
- // Start streaming
- bebop_front_camera.is_streaming = true;
- while (bebop_front_camera.is_streaming) {
- // Wait for a new frame (blocking)
- struct image_t img;
- v4l2_image_get(bebop_front_camera.dev, &img);
-
- BayerToYUV(&img, &img_color, 0, 0);
-
- if (bebop_front_camera.take_shot) {
- // Save the image
- bebop_front_camera_save_shot(&img_color, &img_jpeg, &img);
- bebop_front_camera.take_shot = false;
- }
-
- jpeg_encode_image(&img_color, &img_jpeg, 80, 0);
-
- // Send image with RTP
- rtp_frame_send(
- &video_sock, // UDP socket
- &img_jpeg,
- 0, // Format 422
- 80, // Jpeg-Quality
- 0, // DRI Header
- 0 // 90kHz time increment
- );
-
-
- // Free the image
- v4l2_image_free(bebop_front_camera.dev, &img);
- }
-
- return 0;
-}
-
-/**
- * Initialize the view video
- */
-void bebop_front_camera_init(void)
-{
- // Initialize the V4L2 subdevice (TODO: fix hardcoded path, which and code)
- if (!v4l2_init_subdev("/dev/v4l-subdev1", 0, 0, V4L2_MBUS_FMT_SGBRG10_1X10, MT9F002_WIDTH, MT9F002_HEIGHT)) {
- printf("[bebop_front_camera] Could not initialize the v4l-subdev1 subdevice.\n");
- return;
- }
-
- // Initialize the V4L2 device
- bebop_front_camera.dev = v4l2_init("/dev/video1", MT9F002_WIDTH, MT9F002_HEIGHT, 10, V4L2_PIX_FMT_SGBRG10);
- if (bebop_front_camera.dev == NULL) {
- printf("[bebop_front_camera] Could not initialize the /dev/video1 V4L2 device.\n");
- return;
- }
-
- // Create the shot directory
- char save_name[128];
- sprintf(save_name, "mkdir -p %s", STRINGIFY(BEBOP_FRONT_CAMERA_SHOT_PATH));
- if (system(save_name) != 0) {
- printf("[bebop_front_camera] Could not create shot directory %s.\n", STRINGIFY(BEBOP_FRONT_CAMERA_SHOT_PATH));
- return;
- }
-}
-
-/**
- * Start with streaming
- */
-void bebop_front_camera_start(void)
-{
- // Check if we are already running
- if (bebop_front_camera.is_streaming) {
- return;
- }
-
- // Start the streaming thread
- pthread_t tid;
- if (pthread_create(&tid, NULL, bebop_front_camera_thread, NULL) != 0) {
- printf("[vievideo] Could not create streaming thread.\n");
- return;
- }
-}
-
-/**
- * Stops the streaming
- * This could take some time, because the thread is stopped asynchronous.
- */
-void bebop_front_camera_stop(void)
-{
- // Check if not already stopped streaming
- if (!bebop_front_camera.is_streaming) {
- return;
- }
-
- // Stop the streaming thread
- bebop_front_camera.is_streaming = false;
-
- // Stop the capturing
- if (!v4l2_stop_capture(bebop_front_camera.dev)) {
- printf("[bebop_front_camera] Could not stop capture of %s.\n", bebop_front_camera.dev->name);
- return;
- }
-
- // TODO: wait for the thread to finish to be able to start the thread again!
-}
-
-static void bebop_front_camera_save_shot(struct image_t *img, struct image_t *img_jpeg, struct image_t *raw_img)
-{
-
- // Search for a file where we can write to
- char save_name[128];
- for (; bebop_front_camera.shot_number < 99999; bebop_front_camera.shot_number++) {
- sprintf(save_name, "%s/img_%05d.pgm", STRINGIFY(BEBOP_FRONT_CAMERA_SHOT_PATH), bebop_front_camera.shot_number);
- // Check if file exists or not
- if (access(save_name, F_OK) == -1) {
- FILE *fp = fopen(save_name, "w");
- if (fp == NULL) {
- printf("[bebop_front_camera-thread] Could not write shot %s.\n", save_name);
- } else {
- // Save it to the file and close it
- char pgm_header[] = "P5\n272 272\n255\n";
- fwrite(pgm_header, sizeof(char), 15, fp);
- fwrite(img->buf, sizeof(uint8_t), img->buf_size, fp);
- fclose(fp);
-
- // JPEG
- jpeg_encode_image(img, img_jpeg, 99, 1);
- sprintf(save_name, "%s/img_%05d.jpg", STRINGIFY(BEBOP_FRONT_CAMERA_SHOT_PATH), bebop_front_camera.shot_number);
- fp = fopen(save_name, "w");
- fwrite(img_jpeg->buf, sizeof(uint8_t), img_jpeg->buf_size, fp);
- fclose(fp);
-
- sprintf(save_name, "%s/img_%05d.raw", STRINGIFY(BEBOP_FRONT_CAMERA_SHOT_PATH), bebop_front_camera.shot_number);
- fp = fopen(save_name, "w");
- fwrite(raw_img->buf, sizeof(uint8_t), raw_img->buf_size, fp);
- fclose(fp);
-
- }
-
- // We don't need to seek for a next index anymore
- break;
- }
- }
-}
diff --git a/sw/airborne/modules/computer_vision/bebop_front_camera.h b/sw/airborne/modules/computer_vision/bebop_front_camera.h
deleted file mode 100644
index afaf5255af..0000000000
--- a/sw/airborne/modules/computer_vision/bebop_front_camera.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2012-2014 The Paparazzi Community
- * 2015 Freek van Tienen
- *
- * This file is part of Paparazzi.
- *
- * Paparazzi is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * Paparazzi is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with paparazzi; see the file COPYING. If not, see
- * .
- *
- */
-
-/**
- * @file modules/computer_vision/bebop_front_camera.h
- *
- * Get live images from a RTP/UDP stream
- * and save pictures on internal memory
- *
- * Works on Bebop platforms
- */
-
-#ifndef BEBOP_FRONT_CAMERA_H
-#define BEBOP_FRONT_CAMERA_H
-
-#include "std.h"
-
-// Main viewvideo structure
-struct bebopfrontcamera_t {
- struct v4l2_device *dev; ///< The V4L2 device that is used for the video stream
- uint8_t fps; ///< The amount of frames per second
- volatile bool take_shot; ///< Wether to take an image
- uint16_t shot_number; ///< The last shot number
- volatile bool is_streaming; ///< When the device is streaming
- uint8_t downsize_factor; ///< Downsize factor during the stream
- uint8_t quality_factor; ///< Quality factor during the stream
- bool use_rtp; ///< Stream over RTP
-};
-extern struct bebopfrontcamera_t bebop_front_camera;
-
-// Module functions
-extern void bebop_front_camera_init(void);
-extern void bebop_front_camera_periodic(void); ///< A dummy for now
-extern void bebop_front_camera_start(void);
-extern void bebop_front_camera_stop(void);
-extern void bebop_front_camera_take_shot(bool take);
-
-#endif /* BEBOP_FRONT_CAMERA_H */
-
diff --git a/sw/airborne/modules/computer_vision/cv_ae_awb.c b/sw/airborne/modules/computer_vision/cv_ae_awb.c
index 295fc8283f..79040ff538 100644
--- a/sw/airborne/modules/computer_vision/cv_ae_awb.c
+++ b/sw/airborne/modules/computer_vision/cv_ae_awb.c
@@ -65,10 +65,13 @@ void cv_ae_awb_periodic(void)
uint32_t max_saturated_pixels = yuv_stats.nb_valid_Y / 400; // 0.25%
float adjustment = 1.0f;
+ printf("%d %d\n", bright_pixels, target_bright_pixels);
+
// Fix saturated pixels
if (saturated_pixels > max_saturated_pixels) {
adjustment = 1.0f - ((float)(saturated_pixels - max_saturated_pixels)) / yuv_stats.nb_valid_Y;
- } else if (bright_pixels + target_bright_pixels / 10 < target_bright_pixels) { // Fix bright pixels if outside of 10% of target
+ } else if (bright_pixels + target_bright_pixels / 10 <
+ target_bright_pixels) { // Fix bright pixels if outside of 10% of target
// increase brightness to try and hit the desired number of well exposed pixels
int l = MAX_HIST_Y - 11;
while (bright_pixels < target_bright_pixels && l > 0) {
@@ -78,7 +81,8 @@ void cv_ae_awb_periodic(void)
}
adjustment = (float)(MAX_HIST_Y - 11 + 1) / (l + 1);
- } else if (bright_pixels - target_bright_pixels / 10 > target_bright_pixels) { // Fix bright pixels if outside of 10% of target
+ } else if (bright_pixels - target_bright_pixels / 10 >
+ target_bright_pixels) { // Fix bright pixels if outside of 10% of target
// decrease brightness to try and hit the desired number of well exposed pixels
int l = MAX_HIST_Y - 20;
while (bright_pixels > target_bright_pixels && l < MAX_HIST_Y) {
@@ -105,16 +109,16 @@ void cv_ae_awb_periodic(void)
float gain = 1.;
bool changed = false;
- if (fabs(avgU) > threshold){
+ if (fabs(avgU) > threshold) {
mt9f002.gain_blue -= gain * avgU;
changed = true;
}
- if (fabs(avgV) > threshold){
+ if (fabs(avgV) > threshold) {
mt9f002.gain_red -= gain * avgV;
changed = true;
}
- if (changed){
+ if (changed) {
Bound(mt9f002.gain_blue, 2, 75);
Bound(mt9f002.gain_red, 2, 75);
mt9f002_set_gains(&mt9f002);
diff --git a/sw/airborne/modules/computer_vision/lib/encoding/rtp.c b/sw/airborne/modules/computer_vision/lib/encoding/rtp.c
index d1f4c9c46a..b011bec61e 100644
--- a/sw/airborne/modules/computer_vision/lib/encoding/rtp.c
+++ b/sw/airborne/modules/computer_vision/lib/encoding/rtp.c
@@ -92,24 +92,21 @@ void rtp_frame_test(struct UdpSocket *udp)
* @param[in] format_code 0 for YUV422 and 1 for YUV421
* @param[in] quality_code The JPEG encoding quality
* @param[in] has_dri_header Whether we have an DRI header or not
- * @param[in] delta_t Time between images (if set to 0 or less it is calculated)
+ * @param[in] delta_t Time between images in usec (if set to 0 or less it is calculated)
*/
void rtp_frame_send(struct UdpSocket *udp, struct image_t *img, uint8_t format_code,
- uint8_t quality_code, uint8_t has_dri_header, uint32_t delta_t)
+ uint8_t quality_code, uint8_t has_dri_header, uint32_t frame_time, uint32_t *packet_number)
{
- static uint32_t packetcounter = 0;
- static uint32_t timecounter = 0;
uint32_t offset = 0;
uint32_t jpeg_size = img->buf_size;
uint8_t *jpeg_ptr = img->buf;
#define MAX_PACKET_SIZE 1400
- if (delta_t <= 0) {
+ if (frame_time <= 0) {
struct timeval tv;
gettimeofday(&tv, 0);
- uint32_t t = (tv.tv_sec % (256 * 256)) * 90000 + tv.tv_usec * 9 / 100;
- timecounter = t;
+ frame_time = (tv.tv_sec % (256 * 256)) + tv.tv_usec;
}
// Split frame into packets
@@ -122,31 +119,29 @@ void rtp_frame_send(struct UdpSocket *udp, struct image_t *img, uint8_t format_c
len = jpeg_size;
}
- rtp_packet_send(udp, jpeg_ptr, len, packetcounter, timecounter, offset, lastpacket, img->w, img->h, format_code,
+ rtp_packet_send(udp, jpeg_ptr, len, (*packet_number)++, frame_time, offset, lastpacket, img->w, img->h, format_code,
quality_code, has_dri_header);
jpeg_size -= len;
jpeg_ptr += len;
offset += len;
- packetcounter++;
- }
-
-
- if (delta_t > 0) {
- // timestamp = 1 / 90 000 seconds
- timecounter += delta_t;
}
}
/*
- * The RTP timestamp is in units of 90000Hz. The same timestamp MUST
- appear in each fragment of a given frame. The RTP marker bit MUST be
- set in the last packet of a frame.
+ * The same timestamp MUST appear in each fragment of a given frame.
+ * The RTP marker bit MUST be set in the last packet of a frame.
+ * Extra note: When the time difference between frames is non-constant,
+ there seems to introduce some lag or jitter in the video streaming.
+ One way to solve this is to send the timestamp in units of 90000Hz
+ rather than 100000 (when the frame is received the timestamp is always
+ "late" so the frame is displayed immediately). (1 = 1/90000 s) which
+ is probably stupid but is actually working.
* @param[in] *udp The UDP socket to send the RTP packet over
* @param[in] *Jpeg JPEG encoded image byte buffer
* @param[in] JpegLen The length of the byte buffer
* @param[in] m_SequenceNumber RTP sequence number
- * @param[in] m_Timestamp Timestamp of the image
+ * @param[in] m_Timestamp Timestamp of the image in usec
* @param[in] m_offset 3 byte fragmentation offset for fragmented images
* @param[in] marker_bit RTP marker bit
* @param[in] w The width of the JPEG image
@@ -190,6 +185,7 @@ static void rtp_packet_send(
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* */
+ m_Timestamp *= 9 / 100; // convert timestamp to units of 1 / 90000 Hz
// Prepare the 12 byte RTP header
RtpBuf[0] = 0x80; // RTP version
RtpBuf[1] = 0x1a + (marker_bit << 7); // JPEG payload (26) and marker bit
diff --git a/sw/airborne/modules/computer_vision/lib/encoding/rtp.h b/sw/airborne/modules/computer_vision/lib/encoding/rtp.h
index 88a8075522..2616ebeefa 100644
--- a/sw/airborne/modules/computer_vision/lib/encoding/rtp.h
+++ b/sw/airborne/modules/computer_vision/lib/encoding/rtp.h
@@ -33,7 +33,7 @@
#include "udp_socket.h"
void rtp_frame_send(struct UdpSocket *udp, struct image_t *img, uint8_t format_code, uint8_t quality_code,
- uint8_t has_dri_header, uint32_t delta_t);
+ uint8_t has_dri_header, uint32_t frame_time, uint32_t *packet_number);
void rtp_frame_test(struct UdpSocket *udp);
#endif /* _CV_ENCODING_RTP_H */
diff --git a/sw/airborne/modules/computer_vision/lib/isp/libisp.c b/sw/airborne/modules/computer_vision/lib/isp/libisp.c
index 646592fd09..7997bf1f8e 100644
--- a/sw/airborne/modules/computer_vision/lib/isp/libisp.c
+++ b/sw/airborne/modules/computer_vision/lib/isp/libisp.c
@@ -8,7 +8,7 @@
#include
#include
-#include "libisp.h"
+//#include "libisp.h"
#include "libisp_config.h"
#define AVI_BASE 0x400000
@@ -194,10 +194,6 @@ int configure_isp(struct v4l2_device *dev)
avi_isp_gamma_corrector_gu_lut_set_registers(&isp_ctx, &isp_config.gc_gu_lut);
avi_isp_gamma_corrector_bv_lut_set_registers(&isp_ctx, &isp_config.gc_bv_lut);
avi_isp_chroma_set_registers(&isp_ctx, &isp_config.chroma);
-
- isp_config.statistics_yuv.increments_log2.x_log2_inc = log2(MT9F002_X_ODD_INC_VAL);
- isp_config.statistics_yuv.increments_log2.x_log2_inc = log2(MT9F002_Y_ODD_INC_VAL);
-
avi_isp_statistics_yuv_set_registers(&isp_ctx, &isp_config.statistics_yuv);
avi_isp_edge_enhancement_color_reduction_filter_set_registers(&isp_ctx, &isp_config.eecrf);
avi_isp_edge_enhancement_color_reduction_filter_ee_lut_set_registers(&isp_ctx, &isp_config.eecrf_lut);
diff --git a/sw/airborne/modules/computer_vision/lib/isp/libisp_config.h b/sw/airborne/modules/computer_vision/lib/isp/libisp_config.h
index a1ec2e07b3..07d5e39109 100644
--- a/sw/airborne/modules/computer_vision/lib/isp/libisp_config.h
+++ b/sw/airborne/modules/computer_vision/lib/isp/libisp_config.h
@@ -1,7 +1,7 @@
#ifndef _LIBISP_CONFIG_H
#define _LIBISP_CONFIG_H
-#include "boards/bebop.h"
+#include "boards/bebop/mt9f002.h"
#include "libisp.h"
struct libisp_config isp_config = {
@@ -433,8 +433,8 @@ struct libisp_config isp_config = {
.statistics_yuv = {
.measure_req = {{1, 1}},
.measure_status = {{0, 0}},
- .window_pos_x = {{ .window_x_start = 0, .window_x_end = MT9F002_OUTPUT_WIDTH }},
- .window_pos_y = {{ .window_y_start = 0, .window_y_end = MT9F002_OUTPUT_HEIGHT }},
+ .window_pos_x = {{ .window_x_start = 0, .window_x_end = MT9F002_OUTPUT_WIDTH - 1 }},
+ .window_pos_y = {{ .window_y_start = 0, .window_y_end = MT9F002_OUTPUT_HEIGHT - 1 }},
.circle_pos_x_center = {{ 1088 }},
.circle_pos_x_squared = {{ 1183744 }},
.circle_pos_y_center = {{ 1078 }},
diff --git a/sw/airborne/modules/computer_vision/viewvideo.c b/sw/airborne/modules/computer_vision/viewvideo.c
index d3a48e15cb..2a233c58e5 100644
--- a/sw/airborne/modules/computer_vision/viewvideo.c
+++ b/sw/airborne/modules/computer_vision/viewvideo.c
@@ -68,7 +68,7 @@ PRINT_CONFIG_VAR(VIEWVIDEO_RTP_TIME_INC)
// Define stream framerate
#ifndef VIEWVIDEO_FPS
-#define VIEWVIDEO_FPS 10
+#define VIEWVIDEO_FPS 5
#endif
PRINT_CONFIG_VAR(VIEWVIDEO_FPS)
@@ -112,16 +112,11 @@ struct viewvideo_t viewvideo = {
#endif
};
-#if defined(VIEWVIDEO_CAMERA) && defined(VIEWVIDEO_CAMERA2) && VIEWVIDEO_BROADCAST == true
-#warning Broadcasting dual video stream causes too much udp overhead resulting in unstable streaming
-#warning We recomment using a static VIEWVIDEO_HOST address and VIEWVIDEO_BROADCAST to false
-#endif
-
/**
* Handles all the video streaming and saving of the image shots
* This is a separate thread, so it needs to be thread safe!
*/
-static struct image_t *viewvideo_function(struct UdpSocket *socket, struct image_t *img)
+static struct image_t *viewvideo_function(struct UdpSocket *socket, struct image_t *img, uint32_t *rtp_frame_nr)
{
// Resize image if needed
struct image_t img_small;
@@ -180,19 +175,11 @@ static struct image_t *viewvideo_function(struct UdpSocket *socket, struct image
0, // Format 422
VIEWVIDEO_QUALITY_FACTOR, // Jpeg-Quality
0, // DRI Header
- VIEWVIDEO_RTP_TIME_INC // 90kHz time increment
+ (img->ts.tv_sec * 1000000 + img->ts.tv_usec),
+ rtp_frame_nr
);
- // Extra note: when the time increment is set to 0,
- // it is automaticaly calculated by the send_rtp_frame function
- // based on gettimeofday value. This seems to introduce some lag or jitter.
- // An other way is to compute the time increment and set the correct value.
- // It seems that a lower value is also working (when the frame is received
- // the timestamp is always "late" so the frame is displayed immediately).
- // Here, we set the time increment to the lowest possible value
- // (1 = 1/90000 s) which is probably stupid but is actually working.
}
#endif
-
}
// Free all buffers
@@ -204,14 +191,16 @@ static struct image_t *viewvideo_function(struct UdpSocket *socket, struct image
#ifdef VIEWVIDEO_CAMERA
static struct image_t *viewvideo_function1(struct image_t *img)
{
- return viewvideo_function(&video_sock1, img);
+ static uint32_t rtp_frame_nr = 0;
+ return viewvideo_function(&video_sock1, img, &rtp_frame_nr);
}
#endif
#ifdef VIEWVIDEO_CAMERA2
static struct image_t *viewvideo_function2(struct image_t *img)
{
- return viewvideo_function(&video_sock2, img);
+ static uint32_t rtp_frame_nr = 0;
+ return viewvideo_function(&video_sock2, img, &rtp_frame_nr);
}
#endif