remove non used bebop front cam module, fix cropping in pixel skip, fix isp statistics config, fix rtp streaming hanging

This commit is contained in:
kirkscheper
2016-10-31 17:05:03 +01:00
parent ffe87b9f65
commit d64675e486
13 changed files with 144 additions and 515 deletions
+3 -6
View File
@@ -17,9 +17,9 @@
<define name="MT9F002_GAIN_GREEN2" value="4"/>
<define name="MT9F002_GAIN_RED" value="5"/>
<define name="MT9F002_GAIN_BLUE" value="5"/>
<define name="MT9F002_OUTPUT_SCALER" value="1."/>
<define name="MT9F002_X_ODD_INC_VAL" value="7"/>
<define name="MT9F002_Y_ODD_INC_VAL" value="7"/>
<define name="MT9F002_OUTPUT_SCALER" value="0.25"/>
<define name="MT9F002_X_ODD_INC_VAL" value="1"/>
<define name="MT9F002_Y_ODD_INC_VAL" value="1"/>
<!--define name="USE_SONAR" value="TRUE"/-->
@@ -50,9 +50,6 @@
<define name="VIEWVIDEO_CAMERA2" value="front_camera"/>
<define name="VIEWVIDEO_DOWNSIZE_FACTOR" value="2"/>
<define name="VIEWVIDEO_QUALITY_FACTOR" value="40"/>
<configure name="VIEWVIDEO_BROADCAST" value="TRUE"/>
<configure name="VIEWVIDEO_HOST" value="192.168.42.98"/>
</module>
<module name="cv_ae_awb"/>
-66
View File
@@ -1,66 +0,0 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="bebop_front_camera" dir="computer_vision">
<doc>
<description>
Video streaming for the Bebop front camera
</description>
<define name="BEBOP_FRONT_CAMERA_SHOT_PATH" value="/data/ftp/internal_000/images" description="Path where the images should be saved"/>
<configure name="BEBOP_FRONT_CAMERA_HOST" value="192.168.1.255" description="GCS IP (default: MODEM_HOST)"/>
<configure name="BEBOP_FRONT_CAMERA_PORT_OUT" value="6000" description="Port (default: 5000)"/>
<configure name="BEBOP_FRONT_CAMERA_BROADCAST" value="FALSE|TRUE" description="Enable broadcast of image stream (default: TRUE)"/>
</doc>
<settings>
<dl_settings>
<dl_settings name="video">
<dl_setting var="bebop_front_camera.take_shot" min="0" step="1" max="1" shortname="take_shot" module="computer_vision/bebop_front_camera" handler="take_shot">
<strip_button name="Shoot" icon="digital-camera.png" value="1" group="video"/>
</dl_setting>
</dl_settings>
</dl_settings>
</settings>
<header>
<file name="bebop_front_camera.h"/>
</header>
<init fun="bebop_front_camera_init()"/>
<periodic fun="bebop_front_camera_periodic()" freq="1" start="bebop_front_camera_start()" stop="bebop_front_camera_stop()" autorun="TRUE"/>
<makefile target="ap">
<file name="bebop_front_camera.c"/>
<!-- Include the needed Computer Vision files -->
<include name="modules/computer_vision"/>
<file name="image.c" dir="modules/computer_vision/lib/vision"/>
<file name="v4l2.c" dir="modules/computer_vision/lib/v4l"/>
<file name="jpeg.c" dir="modules/computer_vision/lib/encoding"/>
<file name="rtp.c" dir="modules/computer_vision/lib/encoding"/>
<!-- Random flags -->
<define name="__USE_GNU"/>
<flag name="LDFLAGS" value="lrt"/>
<flag name="LDFLAGS" value="static-libgcc"/>
<raw>
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
</raw>
</makefile>
<makefile target="nps">
<file name="BEBOP_FRONT_CAMERA_nps.c"/>
</makefile>
</module>
-73
View File
@@ -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
+31 -19
View File
@@ -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 <stdio.h>
#include <unistd.h>
@@ -38,10 +39,10 @@
#include <linux/videodev2.h>
#include <linux/v4l2-mediabus.h>
#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);
}
/**
+73
View File
@@ -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
@@ -1,241 +0,0 @@
/*
* Copyright (C) 2012-2014 The Paparazzi Community
* 2015 Freek van Tienen <freek.v.tienen@gmail.com>
*
* 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
* <http://www.gnu.org/licenses/>.
*
*/
/**
* @file modules/computer_vision/bebop_front_camera.c
*/
// Own header
#include "modules/computer_vision/bebop_front_camera.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <math.h>
// 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 <pthread.h>
#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;
}
}
}
@@ -1,58 +0,0 @@
/*
* Copyright (C) 2012-2014 The Paparazzi Community
* 2015 Freek van Tienen <freek.v.tienen@gmail.com>
*
* 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
* <http://www.gnu.org/licenses/>.
*
*/
/**
* @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 */
@@ -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);
@@ -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
@@ -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 */
@@ -8,7 +8,7 @@
#include <sys/mman.h>
#include <sys/ioctl.h>
#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);
@@ -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 }},
@@ -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