From c47cbce1588f2e73f02b6c96ab70f6783900aaa9 Mon Sep 17 00:00:00 2001 From: Ville Ilvonen Date: Thu, 9 Feb 2017 10:23:14 +0200 Subject: [PATCH] capture_example: v4l2 cameras on Aero Added yocto-recipe to build v4l2 capture example to access Aero cameras. This sample app is based on capture.cpp example code TODO: atomisp.h include path directly from kernel Signed-off-by: Ville Ilvonen --- capturev4l2/atomisp.h | 1344 +++++++++++++++++++++++++++++++++++ capturev4l2/atomisp_obj.cpp | 37 + capturev4l2/atomisp_obj.h | 16 + capturev4l2/capture.cpp | 1226 ++++++++++++++++++++++++++++++++ capturev4l2/v4l2_obj.cpp | 591 +++++++++++++++ capturev4l2/v4l2_obj.h | 59 ++ 6 files changed, 3273 insertions(+) create mode 100644 capturev4l2/atomisp.h create mode 100644 capturev4l2/atomisp_obj.cpp create mode 100644 capturev4l2/atomisp_obj.h create mode 100644 capturev4l2/capture.cpp create mode 100644 capturev4l2/v4l2_obj.cpp create mode 100644 capturev4l2/v4l2_obj.h diff --git a/capturev4l2/atomisp.h b/capturev4l2/atomisp.h new file mode 100644 index 0000000..1a63a37 --- /dev/null +++ b/capturev4l2/atomisp.h @@ -0,0 +1,1344 @@ +/* + * Support for Medifield PNW Camera Imaging ISP subsystem. + * + * Copyright (c) 2010 Intel Corporation. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +#ifndef _ATOM_ISP_H +#define _ATOM_ISP_H + +#include +#include +#include + +# define __user + +/* struct media_device_info.driver_version */ +#define ATOMISP_CSS_VERSION_MASK 0x00ffffff +#define ATOMISP_CSS_VERSION_15 KERNEL_VERSION(1, 5, 0) +#define ATOMISP_CSS_VERSION_20 KERNEL_VERSION(2, 0, 0) +#define ATOMISP_CSS_VERSION_21 KERNEL_VERSION(2, 1, 0) + +/* struct media_device_info.hw_revision */ +#define ATOMISP_HW_REVISION_MASK 0x0000ff00 +#define ATOMISP_HW_REVISION_SHIFT 8 +#define ATOMISP_HW_REVISION_ISP2300 0x00 +#define ATOMISP_HW_REVISION_ISP2400 0x10 +#define ATOMISP_HW_REVISION_ISP2401_LEGACY 0x11 +#define ATOMISP_HW_REVISION_ISP2401 0x20 + +#define ATOMISP_HW_STEPPING_MASK 0x000000ff +#define ATOMISP_HW_STEPPING_A0 0x00 +#define ATOMISP_HW_STEPPING_B0 0x10 + +/*ISP binary running mode*/ +#define CI_MODE_PREVIEW 0x8000 +#define CI_MODE_VIDEO 0x4000 +#define CI_MODE_STILL_CAPTURE 0x2000 +#define CI_MODE_CONTINUOUS 0x1000 +#define CI_MODE_NONE 0x0000 + +#define OUTPUT_MODE_FILE 0x0100 +#define OUTPUT_MODE_TEXT 0x0200 + +/* + * Camera HAL sets this flag in v4l2_buffer reserved2 to indicate this + * buffer has a per-frame parameter. + */ +#define ATOMISP_BUFFER_HAS_PER_FRAME_SETTING 0x80000000 + +/* Custom format for RAW capture from M10MO 0x3130314d */ +#define V4L2_PIX_FMT_CUSTOM_M10MO_RAW v4l2_fourcc('M', '1', '0', '1') + +/* Custom media bus formats being used in atomisp */ +#define MEDIA_BUS_FMT_CUSTOM_YUV420 0x8001 +#define MEDIA_BUS_FMT_CUSTOM_YVU420 0x8002 +#define MEDIA_BUS_FMT_CUSTOM_YUV422P 0x8003 +#define MEDIA_BUS_FMT_CUSTOM_YUV444 0x8004 +#define MEDIA_BUS_FMT_CUSTOM_NV12 0x8005 +#define MEDIA_BUS_FMT_CUSTOM_NV21 0x8006 +#define MEDIA_BUS_FMT_CUSTOM_NV16 0x8007 +#define MEDIA_BUS_FMT_CUSTOM_YUYV 0x8008 +#define MEDIA_BUS_FMT_CUSTOM_SBGGR16 0x8009 +#define MEDIA_BUS_FMT_CUSTOM_RGB32 0x800a + +/* Custom media bus format for M10MO RAW capture */ +#define MEDIA_BUS_FMT_CUSTOM_M10MO_RAW 0x800b + +/* Configuration used by Bayer noise reduction and YCC noise reduction */ +struct atomisp_nr_config { + /* [gain] Strength of noise reduction for Bayer NR (Used by Bayer NR) */ + unsigned int bnr_gain; + /* [gain] Strength of noise reduction for YCC NR (Used by YCC NR) */ + unsigned int ynr_gain; + /* [intensity] Sensitivity of Edge (Used by Bayer NR) */ + unsigned int direction; + /* [intensity] coring threshold for Cb (Used by YCC NR) */ + unsigned int threshold_cb; + /* [intensity] coring threshold for Cr (Used by YCC NR) */ + unsigned int threshold_cr; +}; + +/* Temporal noise reduction configuration */ +struct atomisp_tnr_config { + unsigned int gain; /* [gain] Strength of NR */ + unsigned int threshold_y;/* [intensity] Motion sensitivity for Y */ + unsigned int threshold_uv;/* [intensity] Motion sensitivity for U/V */ +}; + +/* Histogram. This contains num_elements values of type unsigned int. + * The data pointer is a DDR pointer (virtual address). + */ +struct atomisp_histogram { + unsigned int num_elements; + void __user *data; +}; + +enum atomisp_ob_mode { + atomisp_ob_mode_none, + atomisp_ob_mode_fixed, + atomisp_ob_mode_raster +}; + +/* Optical black level configuration */ +struct atomisp_ob_config { + /* Obtical black level mode (Fixed / Raster) */ + enum atomisp_ob_mode mode; + /* [intensity] optical black level for GR (relevant for fixed mode) */ + unsigned int level_gr; + /* [intensity] optical black level for R (relevant for fixed mode) */ + unsigned int level_r; + /* [intensity] optical black level for B (relevant for fixed mode) */ + unsigned int level_b; + /* [intensity] optical black level for GB (relevant for fixed mode) */ + unsigned int level_gb; + /* [BQ] 0..63 start position of OB area (relevant for raster mode) */ + unsigned short start_position; + /* [BQ] start..63 end position of OB area (relevant for raster mode) */ + unsigned short end_position; +}; + +/* Edge enhancement (sharpen) configuration */ +struct atomisp_ee_config { + /* [gain] The strength of sharpness. u5_11 */ + unsigned int gain; + /* [intensity] The threshold that divides noises from edge. u8_8 */ + unsigned int threshold; + /* [gain] The strength of sharpness in pell-mell area. u5_11 */ + unsigned int detail_gain; +}; + +struct atomisp_3a_output { + int ae_y; + int awb_cnt; + int awb_gr; + int awb_r; + int awb_b; + int awb_gb; + int af_hpf1; + int af_hpf2; +}; + +enum atomisp_calibration_type { + calibration_type1, + calibration_type2, + calibration_type3 +}; + +struct atomisp_calibration_group { + unsigned int size; + unsigned int type; + unsigned short *calb_grp_values; +}; + +struct atomisp_gc_config { + __u16 gain_k1; + __u16 gain_k2; +}; + +struct atomisp_3a_config { + unsigned int ae_y_coef_r; /* [gain] Weight of R for Y */ + unsigned int ae_y_coef_g; /* [gain] Weight of G for Y */ + unsigned int ae_y_coef_b; /* [gain] Weight of B for Y */ + unsigned int awb_lg_high_raw; /* [intensity] + AWB level gate high for raw */ + unsigned int awb_lg_low; /* [intensity] AWB level gate low */ + unsigned int awb_lg_high; /* [intensity] AWB level gate high */ + int af_fir1_coef[7]; /* [factor] AF FIR coefficients of fir1 */ + int af_fir2_coef[7]; /* [factor] AF FIR coefficients of fir2 */ +}; + +struct atomisp_dvs_grid_info { + uint32_t enable; + uint32_t width; + uint32_t aligned_width; + uint32_t height; + uint32_t aligned_height; + uint32_t bqs_per_grid_cell; + uint32_t num_hor_coefs; + uint32_t num_ver_coefs; +}; + +struct atomisp_dvs_envelop { + unsigned int width; + unsigned int height; +}; + +struct atomisp_grid_info { + uint32_t enable; + uint32_t use_dmem; + uint32_t has_histogram; + uint32_t s3a_width; + uint32_t s3a_height; + uint32_t aligned_width; + uint32_t aligned_height; + uint32_t s3a_bqs_per_grid_cell; + uint32_t deci_factor_log2; + uint32_t elem_bit_depth; +}; + +struct atomisp_dis_vector { + int x; + int y; +}; + + +/** DVS 2.0 Coefficient types. This structure contains 4 pointers to + * arrays that contain the coeffients for each type. + */ +struct atomisp_dvs2_coef_types { + short __user *odd_real; /**< real part of the odd coefficients*/ + short __user *odd_imag; /**< imaginary part of the odd coefficients*/ + short __user *even_real;/**< real part of the even coefficients*/ + short __user *even_imag;/**< imaginary part of the even coefficients*/ +}; + +/* + * DVS 2.0 Statistic types. This structure contains 4 pointers to + * arrays that contain the statistics for each type. + */ +struct atomisp_dvs2_stat_types { + int __user *odd_real; /**< real part of the odd statistics*/ + int __user *odd_imag; /**< imaginary part of the odd statistics*/ + int __user *even_real;/**< real part of the even statistics*/ + int __user *even_imag;/**< imaginary part of the even statistics*/ +}; + +struct atomisp_dis_coefficients { + struct atomisp_dvs_grid_info grid_info; + struct atomisp_dvs2_coef_types hor_coefs; + struct atomisp_dvs2_coef_types ver_coefs; +}; + +struct atomisp_dvs2_statistics { + struct atomisp_dvs_grid_info grid_info; + struct atomisp_dvs2_stat_types hor_prod; + struct atomisp_dvs2_stat_types ver_prod; +}; + +struct atomisp_dis_statistics { + struct atomisp_dvs2_statistics dvs2_stat; + uint32_t exp_id; +}; + +struct atomisp_3a_rgby_output { + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t y; +}; + +/* + * Because we have 2 pipes at max to output metadata, therefore driver will use + * ATOMISP_MAIN_METADATA to specify the metadata from the pipe which keeps + * streaming always and use ATOMISP_SEC_METADATA to specify the metadata from + * the pipe which is streaming by request like capture pipe of ZSL or SDV mode + * as secondary metadata. And for the use case which has only one pipe + * streaming like online capture, ATOMISP_MAIN_METADATA will be used. + */ +enum atomisp_metadata_type { + ATOMISP_MAIN_METADATA = 0, + ATOMISP_SEC_METADATA, + ATOMISP_METADATA_TYPE_NUM, +}; + +struct atomisp_metadata_with_type { + /* to specify which type of metadata to get */ + enum atomisp_metadata_type type; + void __user *data; + uint32_t width; + uint32_t height; + uint32_t stride; /* in bytes */ + uint32_t exp_id; /* exposure ID */ + uint32_t *effective_width; /* mipi packets valid data size */ +}; + +struct atomisp_metadata { + void __user *data; + uint32_t width; + uint32_t height; + uint32_t stride; /* in bytes */ + uint32_t exp_id; /* exposure ID */ + uint32_t *effective_width; /* mipi packets valid data size */ +}; + +struct atomisp_ext_isp_ctrl { + uint32_t id; + uint32_t data; +}; + +struct atomisp_3a_statistics { + struct atomisp_grid_info grid_info; + struct atomisp_3a_output __user *data; + struct atomisp_3a_rgby_output __user *rgby_data; + uint32_t exp_id; /* exposure ID */ + uint32_t isp_config_id; /* isp config ID */ +}; + +/** + * struct atomisp_cont_capture_conf - continuous capture parameters + * @num_captures: number of still images to capture + * @skip_frames: number of frames to skip between 2 captures + * @offset: offset in ring buffer to start capture + * + * For example, to capture 1 frame from past, current, and 1 from future + * and skip one frame between each capture, parameters would be: + * num_captures:3 + * skip_frames:1 + * offset:-2 + */ + +struct atomisp_cont_capture_conf { + int num_captures; + unsigned int skip_frames; + int offset; + __u32 reserved[5]; +}; + +struct atomisp_ae_window { + int x_left; + int x_right; + int y_top; + int y_bottom; + int weight; +}; + +/* White Balance (Gain Adjust) */ +struct atomisp_wb_config { + unsigned int integer_bits; + unsigned int gr; /* unsigned .<16-integer_bits> */ + unsigned int r; /* unsigned .<16-integer_bits> */ + unsigned int b; /* unsigned .<16-integer_bits> */ + unsigned int gb; /* unsigned .<16-integer_bits> */ +}; + +/* Color Space Conversion settings */ +struct atomisp_cc_config { + unsigned int fraction_bits; + int matrix[3 * 3]; /* RGB2YUV Color matrix, signed + <13-fraction_bits>. */ +}; + +/* De pixel noise configuration */ +struct atomisp_de_config { + unsigned int pixelnoise; + unsigned int c1_coring_threshold; + unsigned int c2_coring_threshold; +}; + +/* Chroma enhancement */ +struct atomisp_ce_config { + unsigned char uv_level_min; + unsigned char uv_level_max; +}; + +/* Defect pixel correction configuration */ +struct atomisp_dp_config { + /* [intensity] The threshold of defect Pixel Correction, representing + * the permissible difference of intensity between one pixel and its + * surrounding pixels. Smaller values result in more frequent pixel + * corrections. u0_16 + */ + unsigned int threshold; + /* [gain] The sensitivity of mis-correction. ISP will miss a lot of + * defects if the value is set too large. u8_8 + */ + unsigned int gain; + unsigned int gr; + unsigned int r; + unsigned int b; + unsigned int gb; +}; + +/* XNR threshold */ +struct atomisp_xnr_config { + __u16 threshold; +}; + +/* metadata config */ +struct atomisp_metadata_config { + uint32_t metadata_height; + uint32_t metadata_stride; +}; + +/* + * Generic resolution structure. + */ +struct atomisp_resolution { + uint32_t width; /**< Width */ + uint32_t height; /**< Height */ +}; + +/* + * This specifies the coordinates (x,y) + */ +struct atomisp_zoom_point { + int32_t x; /**< x coordinate */ + int32_t y; /**< y coordinate */ +}; + +/* + * This specifies the region + */ +struct atomisp_zoom_region { + struct atomisp_zoom_point origin; /* Starting point coordinates for the region */ + struct atomisp_resolution resolution; /* Region resolution */ +}; + +struct atomisp_dz_config { + uint32_t dx; /**< Horizontal zoom factor */ + uint32_t dy; /**< Vertical zoom factor */ + struct atomisp_zoom_region zoom_region; /**< region for zoom */ +}; + +struct atomisp_parm { + struct atomisp_grid_info info; + struct atomisp_dvs_grid_info dvs_grid; + struct atomisp_dvs_envelop dvs_envelop; + struct atomisp_wb_config wb_config; + struct atomisp_cc_config cc_config; + struct atomisp_ob_config ob_config; + struct atomisp_de_config de_config; + struct atomisp_dz_config dz_config; + struct atomisp_ce_config ce_config; + struct atomisp_dp_config dp_config; + struct atomisp_nr_config nr_config; + struct atomisp_ee_config ee_config; + struct atomisp_tnr_config tnr_config; + struct atomisp_metadata_config metadata_config; +}; + +struct dvs2_bq_resolution { + int width_bq; /* width [BQ] */ + int height_bq; /* height [BQ] */ +}; + +struct atomisp_dvs2_bq_resolutions { + /* GDC source image size [BQ] */ + struct dvs2_bq_resolution source_bq; + /* GDC output image size [BQ] */ + struct dvs2_bq_resolution output_bq; + /* GDC effective envelope size [BQ] */ + struct dvs2_bq_resolution envelope_bq; + /* isp pipe filter size [BQ] */ + struct dvs2_bq_resolution ispfilter_bq; + /* GDC shit size [BQ] */ + struct dvs2_bq_resolution gdc_shift_bq; +}; + +struct atomisp_dvs_6axis_config { + uint32_t exp_id; + uint32_t width_y; + uint32_t height_y; + uint32_t width_uv; + uint32_t height_uv; + uint32_t *xcoords_y; + uint32_t *ycoords_y; + uint32_t *xcoords_uv; + uint32_t *ycoords_uv; +}; + +struct atomisp_formats_config { + uint32_t video_full_range_flag; +}; + +struct atomisp_parameters { + struct atomisp_wb_config *wb_config; /* White Balance config */ + struct atomisp_cc_config *cc_config; /* Color Correction config */ + struct atomisp_tnr_config *tnr_config; /* Temporal Noise Reduction */ + struct atomisp_ecd_config *ecd_config; /* Eigen Color Demosaicing */ + struct atomisp_ynr_config *ynr_config; /* Y(Luma) Noise Reduction */ + struct atomisp_fc_config *fc_config; /* Fringe Control */ + struct atomisp_formats_config *formats_config; /* Formats Control */ + struct atomisp_cnr_config *cnr_config; /* Chroma Noise Reduction */ + struct atomisp_macc_config *macc_config; /* MACC */ + struct atomisp_ctc_config *ctc_config; /* Chroma Tone Control */ + struct atomisp_aa_config *aa_config; /* Anti-Aliasing */ + struct atomisp_aa_config *baa_config; /* Anti-Aliasing */ + struct atomisp_ce_config *ce_config; + struct atomisp_dvs_6axis_config *dvs_6axis_config; + struct atomisp_ob_config *ob_config; /* Objective Black config */ + struct atomisp_dp_config *dp_config; /* Dead Pixel config */ + struct atomisp_nr_config *nr_config; /* Noise Reduction config */ + struct atomisp_ee_config *ee_config; /* Edge Enhancement config */ + struct atomisp_de_config *de_config; /* Demosaic config */ + struct atomisp_gc_config *gc_config; /* Gamma Correction config */ + struct atomisp_anr_config *anr_config; /* Advanced Noise Reduction */ + struct atomisp_3a_config *a3a_config; /* 3A Statistics config */ + struct atomisp_xnr_config *xnr_config; /* eXtra Noise Reduction */ + struct atomisp_dz_config *dz_config; /* Digital Zoom */ + struct atomisp_cc_config *yuv2rgb_cc_config; /* Color + Correction config */ + struct atomisp_cc_config *rgb2yuv_cc_config; /* Color + Correction config */ + struct atomisp_macc_table *macc_table; + struct atomisp_gamma_table *gamma_table; + struct atomisp_ctc_table *ctc_table; + struct atomisp_xnr_table *xnr_table; + struct atomisp_rgb_gamma_table *r_gamma_table; + struct atomisp_rgb_gamma_table *g_gamma_table; + struct atomisp_rgb_gamma_table *b_gamma_table; + struct atomisp_vector *motion_vector; /* For 2-axis DVS */ + struct atomisp_shading_table *shading_table; + struct atomisp_morph_table *morph_table; + struct atomisp_dvs_coefficients *dvs_coefs; /* DVS 1.0 coefficients */ + struct atomisp_dvs2_coefficients *dvs2_coefs; /* DVS 2.0 coefficients */ + struct atomisp_capture_config *capture_config; + struct atomisp_anr_thres *anr_thres; + + void *lin_2500_config; /* Skylake: Linearization config */ + void *obgrid_2500_config; /* Skylake: OBGRID config */ + void *bnr_2500_config; /* Skylake: bayer denoise config */ + void *shd_2500_config; /* Skylake: shading config */ + void *dm_2500_config; /* Skylake: demosaic config */ + void *rgbpp_2500_config; /* Skylake: RGBPP config */ + void *dvs_stat_2500_config; /* Skylake: DVS STAT config */ + void *lace_stat_2500_config; /* Skylake: LACE STAT config */ + void *yuvp1_2500_config; /* Skylake: yuvp1 config */ + void *yuvp2_2500_config; /* Skylake: yuvp2 config */ + void *tnr_2500_config; /* Skylake: TNR config */ + void *dpc_2500_config; /* Skylake: DPC config */ + void *awb_2500_config; /* Skylake: auto white balance config */ + void *awb_fr_2500_config; /* Skylake: auto white balance filter response config */ + void *anr_2500_config; /* Skylake: ANR config */ + void *af_2500_config; /* Skylake: auto focus config */ + void *ae_2500_config; /* Skylake: auto exposure config */ + void *bds_2500_config; /* Skylake: bayer downscaler config */ + void *dvs_2500_config; /* Skylake: digital video stabilization config */ + void *res_mgr_2500_config; + + /* + * Output frame pointer the config is to be applied to (optional), + * set to NULL to make this config is applied as global. + */ + void *output_frame; + /* + * Unique ID to track which config was actually applied to a particular + * frame, driver will send this id back with output frame together. + */ + uint32_t isp_config_id; + + /* + * Switch to control per_frame setting: + * 0: this is a global setting + * 1: this is a per_frame setting + * PLEASE KEEP THIS AT THE END OF THE STRUCTURE!! + */ + uint32_t per_frame_setting; +}; + +#define ATOMISP_GAMMA_TABLE_SIZE 1024 +struct atomisp_gamma_table { + unsigned short data[ATOMISP_GAMMA_TABLE_SIZE]; +}; + +/* Morphing table for advanced ISP. + * Each line of width elements takes up COORD_TABLE_EXT_WIDTH elements + * in memory. + */ +#define ATOMISP_MORPH_TABLE_NUM_PLANES 6 +struct atomisp_morph_table { + unsigned int enabled; + + unsigned int height; + unsigned int width; /* number of valid elements per line */ + unsigned short __user *coordinates_x[ATOMISP_MORPH_TABLE_NUM_PLANES]; + unsigned short __user *coordinates_y[ATOMISP_MORPH_TABLE_NUM_PLANES]; +}; + +#define ATOMISP_NUM_SC_COLORS 4 +#define ATOMISP_SC_FLAG_QUERY (1 << 0) + +struct atomisp_shading_table { + __u32 enable; + + __u32 sensor_width; + __u32 sensor_height; + __u32 width; + __u32 height; + __u32 fraction_bits; + + __u16 *data[ATOMISP_NUM_SC_COLORS]; +}; + +struct atomisp_makernote_info { + /* bits 31-16: numerator, bits 15-0: denominator */ + unsigned int focal_length; + /* bits 31-16: numerator, bits 15-0: denominator*/ + unsigned int f_number_curr; + /* + * bits 31-24: max f-number numerator + * bits 23-16: max f-number denominator + * bits 15-8: min f-number numerator + * bits 7-0: min f-number denominator + */ + unsigned int f_number_range; +}; + +/* parameter for MACC */ +#define ATOMISP_NUM_MACC_AXES 16 +struct atomisp_macc_table { + short data[4 * ATOMISP_NUM_MACC_AXES]; +}; + +struct atomisp_macc_config { + int color_effect; + struct atomisp_macc_table table; +}; + +/* Parameter for ctc parameter control */ +#define ATOMISP_CTC_TABLE_SIZE 1024 +struct atomisp_ctc_table { + unsigned short data[ATOMISP_CTC_TABLE_SIZE]; +}; + +/* Parameter for overlay image loading */ +struct atomisp_overlay { + /* the frame containing the overlay data The overlay frame width should + * be the multiples of 2*ISP_VEC_NELEMS. The overlay frame height + * should be the multiples of 2. + */ + struct v4l2_framebuffer *frame; + /* Y value of overlay background */ + unsigned char bg_y; + /* U value of overlay background */ + char bg_u; + /* V value of overlay background */ + char bg_v; + /* the blending percent of input data for Y subpixels */ + unsigned char blend_input_perc_y; + /* the blending percent of input data for U subpixels */ + unsigned char blend_input_perc_u; + /* the blending percent of input data for V subpixels */ + unsigned char blend_input_perc_v; + /* the blending percent of overlay data for Y subpixels */ + unsigned char blend_overlay_perc_y; + /* the blending percent of overlay data for U subpixels */ + unsigned char blend_overlay_perc_u; + /* the blending percent of overlay data for V subpixels */ + unsigned char blend_overlay_perc_v; + /* the overlay start x pixel position on output frame It should be the + multiples of 2*ISP_VEC_NELEMS. */ + unsigned int overlay_start_x; + /* the overlay start y pixel position on output frame It should be the + multiples of 2. */ + unsigned int overlay_start_y; +}; + +/* Sensor resolution specific data for AE calculation.*/ +struct atomisp_sensor_mode_data { + unsigned int coarse_integration_time_min; + unsigned int coarse_integration_time_max_margin; + unsigned int fine_integration_time_min; + unsigned int fine_integration_time_max_margin; + unsigned int fine_integration_time_def; + unsigned int frame_length_lines; + unsigned int line_length_pck; + unsigned int read_mode; + unsigned int vt_pix_clk_freq_mhz; + unsigned int crop_horizontal_start; /* Sensor crop start cord. (x0,y0)*/ + unsigned int crop_vertical_start; + unsigned int crop_horizontal_end; /* Sensor crop end cord. (x1,y1)*/ + unsigned int crop_vertical_end; + unsigned int output_width; /* input size to ISP after binning/scaling */ + unsigned int output_height; + uint8_t binning_factor_x; /* horizontal binning factor used */ + uint8_t binning_factor_y; /* vertical binning factor used */ + uint16_t hts; +}; + +struct atomisp_exposure { + unsigned int integration_time[8]; + unsigned int shutter_speed[8]; + unsigned int gain[4]; + unsigned int aperture; +}; + +/* For texture streaming. */ +struct atomisp_bc_video_package { + int ioctl_cmd; + int device_id; + int inputparam; + int outputparam; +}; + +enum atomisp_focus_hp { + ATOMISP_FOCUS_HP_IN_PROGRESS = (1U << 2), + ATOMISP_FOCUS_HP_COMPLETE = (2U << 2), + ATOMISP_FOCUS_HP_FAILED = (3U << 2) +}; + +/* Masks */ +#define ATOMISP_FOCUS_STATUS_MOVING (1U << 0) +#define ATOMISP_FOCUS_STATUS_ACCEPTS_NEW_MOVE (1U << 1) +#define ATOMISP_FOCUS_STATUS_HOME_POSITION (3U << 2) + +enum atomisp_camera_port { + ATOMISP_CAMERA_PORT_SECONDARY, + ATOMISP_CAMERA_PORT_PRIMARY, + ATOMISP_CAMERA_PORT_TERTIARY, + ATOMISP_CAMERA_NR_PORTS +}; + +/* Flash modes. Default is off. + * Setting a flash to TORCH or INDICATOR mode will automatically + * turn it on. Setting it to FLASH mode will not turn on the flash + * until the FLASH_STROBE command is sent. */ +enum atomisp_flash_mode { + ATOMISP_FLASH_MODE_OFF, + ATOMISP_FLASH_MODE_FLASH, + ATOMISP_FLASH_MODE_TORCH, + ATOMISP_FLASH_MODE_INDICATOR, +}; + +/* Flash statuses, used by atomisp driver to check before starting + * flash and after having started flash. */ +enum atomisp_flash_status { + ATOMISP_FLASH_STATUS_OK, + ATOMISP_FLASH_STATUS_HW_ERROR, + ATOMISP_FLASH_STATUS_INTERRUPTED, + ATOMISP_FLASH_STATUS_TIMEOUT, +}; + +/* Frame status. This is used to detect corrupted frames and flash + * exposed frames. Usually, the first 2 frames coming out of the sensor + * are corrupted. When using flash, the frame before and the frame after + * the flash exposed frame may be partially exposed by flash. The ISP + * statistics for these frames should not be used by the 3A library. + * The frame status value can be found in the "reserved" field in the + * v4l2_buffer struct. */ +enum atomisp_frame_status { + ATOMISP_FRAME_STATUS_OK, + ATOMISP_FRAME_STATUS_CORRUPTED, + ATOMISP_FRAME_STATUS_FLASH_EXPOSED, + ATOMISP_FRAME_STATUS_FLASH_PARTIAL, + ATOMISP_FRAME_STATUS_FLASH_FAILED, +}; + +enum atomisp_acc_type { + ATOMISP_ACC_STANDALONE, /* Stand-alone acceleration */ + ATOMISP_ACC_OUTPUT, /* Accelerator stage on output frame */ + ATOMISP_ACC_VIEWFINDER /* Accelerator stage on viewfinder frame */ +}; + +enum atomisp_acc_arg_type { + ATOMISP_ACC_ARG_SCALAR_IN, /* Scalar input argument */ + ATOMISP_ACC_ARG_SCALAR_OUT, /* Scalar output argument */ + ATOMISP_ACC_ARG_SCALAR_IO, /* Scalar in/output argument */ + ATOMISP_ACC_ARG_PTR_IN, /* Pointer input argument */ + ATOMISP_ACC_ARG_PTR_OUT, /* Pointer output argument */ + ATOMISP_ACC_ARG_PTR_IO, /* Pointer in/output argument */ + ATOMISP_ARG_PTR_NOFLUSH, /* Pointer argument will not be flushed */ + ATOMISP_ARG_PTR_STABLE, /* Pointer input argument that is stable */ + ATOMISP_ACC_ARG_FRAME /* Frame argument */ +}; + +/** ISP memories, isp2400 */ +enum atomisp_acc_memory { + ATOMISP_ACC_MEMORY_PMEM0 = 0, + ATOMISP_ACC_MEMORY_DMEM0, + /* for backward compatibility */ + ATOMISP_ACC_MEMORY_DMEM = ATOMISP_ACC_MEMORY_DMEM0, + ATOMISP_ACC_MEMORY_VMEM0, + ATOMISP_ACC_MEMORY_VAMEM0, + ATOMISP_ACC_MEMORY_VAMEM1, + ATOMISP_ACC_MEMORY_VAMEM2, + ATOMISP_ACC_MEMORY_HMEM0, + ATOMISP_ACC_NR_MEMORY +}; + +enum atomisp_ext_isp_id { + EXT_ISP_CID_ISO = 0, + EXT_ISP_CID_CAPTURE_HDR, + EXT_ISP_CID_CAPTURE_LLS, + EXT_ISP_CID_FOCUS_MODE, + EXT_ISP_CID_FOCUS_EXECUTION, + EXT_ISP_CID_TOUCH_POSX, + EXT_ISP_CID_TOUCH_POSY, + EXT_ISP_CID_CAF_STATUS, + EXT_ISP_CID_AF_STATUS, + EXT_ISP_CID_GET_AF_MODE, + EXT_ISP_CID_CAPTURE_BURST, + EXT_ISP_CID_FLASH_MODE, + EXT_ISP_CID_ZOOM, + EXT_ISP_CID_SHOT_MODE +}; + +#define EXT_ISP_FOCUS_MODE_NORMAL 0 +#define EXT_ISP_FOCUS_MODE_MACRO 1 +#define EXT_ISP_FOCUS_MODE_TOUCH_AF 2 +#define EXT_ISP_FOCUS_MODE_PREVIEW_CAF 3 +#define EXT_ISP_FOCUS_MODE_MOVIE_CAF 4 +#define EXT_ISP_FOCUS_MODE_FACE_CAF 5 +#define EXT_ISP_FOCUS_MODE_TOUCH_MACRO 6 +#define EXT_ISP_FOCUS_MODE_TOUCH_CAF 7 + +#define EXT_ISP_FOCUS_STOP 0 +#define EXT_ISP_FOCUS_SEARCH 1 +#define EXT_ISP_PAN_FOCUSING 2 + +#define EXT_ISP_CAF_RESTART_CHECK 1 +#define EXT_ISP_CAF_STATUS_FOCUSING 2 +#define EXT_ISP_CAF_STATUS_SUCCESS 3 +#define EXT_ISP_CAF_STATUS_FAIL 4 + +#define EXT_ISP_AF_STATUS_INVALID 1 +#define EXT_ISP_AF_STATUS_FOCUSING 2 +#define EXT_ISP_AF_STATUS_SUCCESS 3 +#define EXT_ISP_AF_STATUS_FAIL 4 + +enum atomisp_burst_capture_options { + EXT_ISP_BURST_CAPTURE_CTRL_START = 0, + EXT_ISP_BURST_CAPTURE_CTRL_STOP +}; + +#define EXT_ISP_FLASH_MODE_OFF 0 +#define EXT_ISP_FLASH_MODE_ON 1 +#define EXT_ISP_FLASH_MODE_AUTO 2 +#define EXT_ISP_LED_TORCH_OFF 3 +#define EXT_ISP_LED_TORCH_ON 4 + +#define EXT_ISP_SHOT_MODE_AUTO 0 +#define EXT_ISP_SHOT_MODE_BEAUTY_FACE 1 +#define EXT_ISP_SHOT_MODE_BEST_PHOTO 2 +#define EXT_ISP_SHOT_MODE_DRAMA 3 +#define EXT_ISP_SHOT_MODE_BEST_FACE 4 +#define EXT_ISP_SHOT_MODE_ERASER 5 +#define EXT_ISP_SHOT_MODE_PANORAMA 6 +#define EXT_ISP_SHOT_MODE_RICH_TONE_HDR 7 +#define EXT_ISP_SHOT_MODE_NIGHT 8 +#define EXT_ISP_SHOT_MODE_SOUND_SHOT 9 +#define EXT_ISP_SHOT_MODE_ANIMATED_PHOTO 10 +#define EXT_ISP_SHOT_MODE_SPORTS 11 + +struct atomisp_sp_arg { + enum atomisp_acc_arg_type type; /* Type of SP argument */ + void *value; /* Value of SP argument */ + unsigned int size; /* Size of SP argument */ +}; + +/* Acceleration API */ + +/* For CSS 1.0 only */ +struct atomisp_acc_fw_arg { + unsigned int fw_handle; + unsigned int index; + void __user *value; + size_t size; +}; + +/* + * Set arguments after first mapping with ATOMISP_IOC_ACC_S_MAPPED_ARG. + */ +struct atomisp_acc_s_mapped_arg { + unsigned int fw_handle; + __u32 memory; /* one of enum atomisp_acc_memory */ + size_t length; + unsigned long css_ptr; +}; + +struct atomisp_acc_fw_abort { + unsigned int fw_handle; + /* Timeout in us */ + unsigned int timeout; +}; + +struct atomisp_acc_fw_load { + unsigned int size; + unsigned int fw_handle; + void __user *data; +}; + +/* + * Load firmware to specified pipeline. + */ +struct atomisp_acc_fw_load_to_pipe { + __u32 flags; /* Flags, see below for valid values */ + unsigned int fw_handle; /* Handle, filled by kernel. */ + __u32 size; /* Firmware binary size */ + void __user *data; /* Pointer to firmware */ + __u32 type; /* Binary type */ + __u32 reserved[3]; /* Set to zero */ +}; + +#define ATOMISP_ACC_FW_LOAD_FL_PREVIEW (1 << 0) +#define ATOMISP_ACC_FW_LOAD_FL_COPY (1 << 1) +#define ATOMISP_ACC_FW_LOAD_FL_VIDEO (1 << 2) +#define ATOMISP_ACC_FW_LOAD_FL_CAPTURE (1 << 3) +#define ATOMISP_ACC_FW_LOAD_FL_ACC (1 << 4) +#define ATOMISP_ACC_FW_LOAD_FL_ENABLE (1 << 16) + +#define ATOMISP_ACC_FW_LOAD_TYPE_NONE 0 /* Normal binary: don't use */ +#define ATOMISP_ACC_FW_LOAD_TYPE_OUTPUT 1 /* Stage on output */ +#define ATOMISP_ACC_FW_LOAD_TYPE_VIEWFINDER 2 /* Stage on viewfinder */ +#define ATOMISP_ACC_FW_LOAD_TYPE_STANDALONE 3 /* Stand-alone acceleration */ + +struct atomisp_acc_map { + __u32 flags; /* Flags, see list below */ + __u32 length; /* Length of data in bytes */ + void __user *user_ptr; /* Pointer into user space */ + unsigned long css_ptr; /* Pointer into CSS address space */ + __u32 reserved[4]; /* Set to zero */ +}; + +#define ATOMISP_MAP_FLAG_NOFLUSH 0x0001 /* Do not flush cache */ +#define ATOMISP_MAP_FLAG_CACHED 0x0002 /* Enable cache */ + +struct atomisp_acc_state { + __u32 flags; /* Flags, see list below */ +#define ATOMISP_STATE_FLAG_ENABLE ATOMISP_ACC_FW_LOAD_FL_ENABLE + unsigned int fw_handle; +}; + +/* + * V4L2 private internal data interface. + * ----------------------------------------------------------------------------- + * struct v4l2_private_int_data - request private data stored in video device + * internal memory. + * @size: sanity check to ensure userspace's buffer fits whole private data. + * If not, kernel will make partial copy (or nothing if @size == 0). + * @size is always corrected for the minimum necessary if IOCTL returns + * no error. + * @data: pointer to userspace buffer. + */ +struct v4l2_private_int_data { + __u32 size; + void __user *data; + __u32 reserved[2]; +}; + +enum atomisp_sensor_ae_bracketing_mode { + SENSOR_AE_BRACKETING_MODE_OFF = 0, + SENSOR_AE_BRACKETING_MODE_SINGLE, /* back to SW standby after bracketing */ + SENSOR_AE_BRACKETING_MODE_SINGLE_TO_STREAMING, /* back to normal streaming after bracketing */ + SENSOR_AE_BRACKETING_MODE_LOOP, /* continue AE bracketing in loop mode */ +}; + +struct atomisp_sensor_ae_bracketing_info { + unsigned int modes; /* bit mask to indicate supported modes */ + unsigned int lut_depth; +}; + +struct atomisp_sensor_ae_bracketing_lut_entry { + __u16 coarse_integration_time; + __u16 analog_gain; + __u16 digital_gain; +}; + +struct atomisp_sensor_ae_bracketing_lut { + struct atomisp_sensor_ae_bracketing_lut_entry *lut; + unsigned int lut_size; +}; + +/*Private IOCTLs for ISP */ +#define ATOMISP_IOC_G_XNR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 0, int) +#define ATOMISP_IOC_S_XNR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 0, int) +#define ATOMISP_IOC_G_NR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 1, struct atomisp_nr_config) +#define ATOMISP_IOC_S_NR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 1, struct atomisp_nr_config) +#define ATOMISP_IOC_G_TNR \ + _IOR('v', BASE_VIDIOC_PRIVATE + 2, struct atomisp_tnr_config) +#define ATOMISP_IOC_S_TNR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 2, struct atomisp_tnr_config) +#define ATOMISP_IOC_G_HISTOGRAM \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 3, struct atomisp_histogram) +#define ATOMISP_IOC_S_HISTOGRAM \ + _IOW('v', BASE_VIDIOC_PRIVATE + 3, struct atomisp_histogram) +#define ATOMISP_IOC_G_BLACK_LEVEL_COMP \ + _IOR('v', BASE_VIDIOC_PRIVATE + 4, struct atomisp_ob_config) +#define ATOMISP_IOC_S_BLACK_LEVEL_COMP \ + _IOW('v', BASE_VIDIOC_PRIVATE + 4, struct atomisp_ob_config) +#define ATOMISP_IOC_G_EE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 5, struct atomisp_ee_config) +#define ATOMISP_IOC_S_EE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 5, struct atomisp_ee_config) +/* Digital Image Stabilization: + * 1. get dis statistics: reads DIS statistics from ISP (every frame) + * 2. set dis coefficients: set DIS filter coefficients (one time) + * 3. set dis motion vecotr: set motion vector (result of DIS, every frame) + */ +#define ATOMISP_IOC_G_DIS_STAT \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_dis_statistics) + +#define ATOMISP_IOC_G_DVS2_BQ_RESOLUTIONS \ + _IOR('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_dvs2_bq_resolutions) + +#define ATOMISP_IOC_S_DIS_COEFS \ + _IOW('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_dis_coefficients) + +#define ATOMISP_IOC_S_DIS_VECTOR \ + _IOW('v', BASE_VIDIOC_PRIVATE + 6, struct atomisp_dvs_6axis_config) + +#define ATOMISP_IOC_G_3A_STAT \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 7, struct atomisp_3a_statistics) +#define ATOMISP_IOC_G_ISP_PARM \ + _IOR('v', BASE_VIDIOC_PRIVATE + 8, struct atomisp_parm) +#define ATOMISP_IOC_S_ISP_PARM \ + _IOW('v', BASE_VIDIOC_PRIVATE + 8, struct atomisp_parm) +#define ATOMISP_IOC_G_ISP_GAMMA \ + _IOR('v', BASE_VIDIOC_PRIVATE + 9, struct atomisp_gamma_table) +#define ATOMISP_IOC_S_ISP_GAMMA \ + _IOW('v', BASE_VIDIOC_PRIVATE + 9, struct atomisp_gamma_table) +#define ATOMISP_IOC_G_ISP_GDC_TAB \ + _IOR('v', BASE_VIDIOC_PRIVATE + 10, struct atomisp_morph_table) +#define ATOMISP_IOC_S_ISP_GDC_TAB \ + _IOW('v', BASE_VIDIOC_PRIVATE + 10, struct atomisp_morph_table) +#define ATOMISP_IOC_ISP_MAKERNOTE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 11, struct atomisp_makernote_info) + +/* macc parameter control*/ +#define ATOMISP_IOC_G_ISP_MACC \ + _IOR('v', BASE_VIDIOC_PRIVATE + 12, struct atomisp_macc_config) +#define ATOMISP_IOC_S_ISP_MACC \ + _IOW('v', BASE_VIDIOC_PRIVATE + 12, struct atomisp_macc_config) + +/* Defect pixel detection & Correction */ +#define ATOMISP_IOC_G_ISP_BAD_PIXEL_DETECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 13, struct atomisp_dp_config) +#define ATOMISP_IOC_S_ISP_BAD_PIXEL_DETECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 13, struct atomisp_dp_config) + +/* False Color Correction */ +#define ATOMISP_IOC_G_ISP_FALSE_COLOR_CORRECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 14, struct atomisp_de_config) +#define ATOMISP_IOC_S_ISP_FALSE_COLOR_CORRECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 14, struct atomisp_de_config) + +/* ctc parameter control */ +#define ATOMISP_IOC_G_ISP_CTC \ + _IOR('v', BASE_VIDIOC_PRIVATE + 15, struct atomisp_ctc_table) +#define ATOMISP_IOC_S_ISP_CTC \ + _IOW('v', BASE_VIDIOC_PRIVATE + 15, struct atomisp_ctc_table) + +/* white balance Correction */ +#define ATOMISP_IOC_G_ISP_WHITE_BALANCE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 16, struct atomisp_wb_config) +#define ATOMISP_IOC_S_ISP_WHITE_BALANCE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 16, struct atomisp_wb_config) + +/* fpn table loading */ +#define ATOMISP_IOC_S_ISP_FPN_TABLE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 17, struct v4l2_framebuffer) + +/* overlay image loading */ +#define ATOMISP_IOC_G_ISP_OVERLAY \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 18, struct atomisp_overlay) +#define ATOMISP_IOC_S_ISP_OVERLAY \ + _IOW('v', BASE_VIDIOC_PRIVATE + 18, struct atomisp_overlay) + +/* bcd driver bridge */ +#define ATOMISP_IOC_CAMERA_BRIDGE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 19, struct atomisp_bc_video_package) + +/* Sensor resolution specific info for AE */ +#define ATOMISP_IOC_G_SENSOR_MODE_DATA \ + _IOR('v', BASE_VIDIOC_PRIVATE + 20, struct atomisp_sensor_mode_data) + +#define ATOMISP_IOC_S_EXPOSURE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 21, struct atomisp_exposure) + +/* sensor calibration registers group */ +#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_calibration_group) + +/* white balance Correction */ +#define ATOMISP_IOC_G_3A_CONFIG \ + _IOR('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config) +#define ATOMISP_IOC_S_3A_CONFIG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config) + +/* Accelerate ioctls */ +#define ATOMISP_IOC_ACC_LOAD \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 24, struct atomisp_acc_fw_load) + +#define ATOMISP_IOC_ACC_UNLOAD \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 24, unsigned int) + +/* For CSS 1.0 only */ +#define ATOMISP_IOC_ACC_S_ARG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 24, struct atomisp_acc_fw_arg) + +#define ATOMISP_IOC_ACC_START \ + _IOW('v', BASE_VIDIOC_PRIVATE + 24, unsigned int) + +#define ATOMISP_IOC_ACC_WAIT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 25, unsigned int) + +#define ATOMISP_IOC_ACC_ABORT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 25, struct atomisp_acc_fw_abort) + +#define ATOMISP_IOC_ACC_DESTAB \ + _IOW('v', BASE_VIDIOC_PRIVATE + 25, struct atomisp_acc_fw_arg) + +/* sensor OTP memory read */ +#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 26, struct v4l2_private_int_data) + +/* LCS (shading) table write */ +#define ATOMISP_IOC_S_ISP_SHD_TAB \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_shading_table) + +/* Gamma Correction */ +#define ATOMISP_IOC_G_ISP_GAMMA_CORRECTION \ + _IOR('v', BASE_VIDIOC_PRIVATE + 28, struct atomisp_gc_config) + +#define ATOMISP_IOC_S_ISP_GAMMA_CORRECTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 28, struct atomisp_gc_config) + +/* motor internal memory read */ +#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 29, struct v4l2_private_int_data) + +/* + * Ioctls to map and unmap user buffers to CSS address space for acceleration. + * User fills fields length and user_ptr and sets other fields to zero, + * kernel may modify the flags and sets css_ptr. + */ +#define ATOMISP_IOC_ACC_MAP \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 30, struct atomisp_acc_map) + +/* User fills fields length, user_ptr, and css_ptr and zeroes other fields. */ +#define ATOMISP_IOC_ACC_UNMAP \ + _IOW('v', BASE_VIDIOC_PRIVATE + 30, struct atomisp_acc_map) + +#define ATOMISP_IOC_ACC_S_MAPPED_ARG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 30, struct atomisp_acc_s_mapped_arg) + +#define ATOMISP_IOC_ACC_LOAD_TO_PIPE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 31, struct atomisp_acc_fw_load_to_pipe) + +#define ATOMISP_IOC_S_PARAMETERS \ + _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters) + +#define ATOMISP_IOC_S_CONT_CAPTURE_CONFIG \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 33, struct atomisp_cont_capture_conf) + +#define ATOMISP_IOC_G_METADATA \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata) + +#define ATOMISP_IOC_G_METADATA_BY_TYPE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata_with_type) + +#define ATOMISP_IOC_EXT_ISP_CTRL \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 35, struct atomisp_ext_isp_ctrl) + +#define ATOMISP_IOC_EXP_ID_UNLOCK \ + _IOW('v', BASE_VIDIOC_PRIVATE + 36, int) + +#define ATOMISP_IOC_EXP_ID_CAPTURE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 37, int) + +#define ATOMISP_IOC_S_ENABLE_DZ_CAPT_PIPE \ + _IOWR('v', BASE_VIDIOC_PRIVATE + 38, unsigned int) + +#define ATOMISP_IOC_G_FORMATS_CONFIG \ + _IOR('v', BASE_VIDIOC_PRIVATE + 39, struct atomisp_formats_config) + +#define ATOMISP_IOC_S_FORMATS_CONFIG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 39, struct atomisp_formats_config) + +#define ATOMISP_IOC_S_EXPOSURE_WINDOW \ + _IOW('v', BASE_VIDIOC_PRIVATE + 40, struct atomisp_ae_window) + +#define ATOMISP_IOC_S_ACC_STATE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 41, struct atomisp_acc_state) + +#define ATOMISP_IOC_G_ACC_STATE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 41, struct atomisp_acc_state) + +#define ATOMISP_IOC_INJECT_A_FAKE_EVENT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 42, int) + +#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO \ + _IOR('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_info) + +#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE \ + _IOW('v', BASE_VIDIOC_PRIVATE + 43, unsigned int) + +#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE \ + _IOR('v', BASE_VIDIOC_PRIVATE + 43, unsigned int) + +#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT \ + _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_lut) + +#define ATOMISP_IOC_G_INVALID_FRAME_NUM \ + _IOR('v', BASE_VIDIOC_PRIVATE + 44, unsigned int) + +#define ATOMISP_IOC_S_ARRAY_RESOLUTION \ + _IOW('v', BASE_VIDIOC_PRIVATE + 45, struct atomisp_resolution) + +/* for depth mode sensor frame sync compensation */ +#define ATOMISP_IOC_G_DEPTH_SYNC_COMP \ + _IOR('v', BASE_VIDIOC_PRIVATE + 46, unsigned int) + +#define ATOMISP_IOC_S_SENSOR_EE_CONFIG \ + _IOW('v', BASE_VIDIOC_PRIVATE + 47, unsigned int) + +/* + * Reserved ioctls. We have customer implementing it internally. + * We can't use both numbers to not cause ABI conflict. + * Anyway, those ioctls are hacks and not implemented by us: + * + * #define ATOMISP_IOC_G_SENSOR_REG \ + * _IOW('v', BASE_VIDIOC_PRIVATE + 55, struct atomisp_sensor_regs) + * #define ATOMISP_IOC_S_SENSOR_REG \ + * _IOW('v', BASE_VIDIOC_PRIVATE + 56, struct atomisp_sensor_regs) + */ + +/* ISP Private control IDs */ +#define V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION \ + (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_ATOMISP_POSTPROCESS_GDC_CAC \ + (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_ATOMISP_VIDEO_STABLIZATION \ + (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_ATOMISP_FIXED_PATTERN_NR \ + (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_ATOMISP_FALSE_COLOR_CORRECTION \ + (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_ATOMISP_LOW_LIGHT \ + (V4L2_CID_PRIVATE_BASE + 5) + +/* Camera class: + * Exposure, Flash and privacy (indicator) light controls, to be upstreamed */ +#define V4L2_CID_CAMERA_LASTP1 (V4L2_CID_CAMERA_CLASS_BASE + 1024) + +#define V4L2_CID_FOCAL_ABSOLUTE (V4L2_CID_CAMERA_LASTP1 + 0) +#define V4L2_CID_FNUMBER_ABSOLUTE (V4L2_CID_CAMERA_LASTP1 + 1) +#define V4L2_CID_FNUMBER_RANGE (V4L2_CID_CAMERA_LASTP1 + 2) + +/* Flash related CIDs, see also: + * http://linuxtv.org/downloads/v4l-dvb-apis/extended-controls.html\ + * #flash-controls */ + +/* Request a number of flash-exposed frames. The frame status can be + * found in the reserved field in the v4l2_buffer struct. */ +#define V4L2_CID_REQUEST_FLASH (V4L2_CID_CAMERA_LASTP1 + 3) +/* Query flash driver status. See enum atomisp_flash_status above. */ +#define V4L2_CID_FLASH_STATUS (V4L2_CID_CAMERA_LASTP1 + 5) +/* Set the flash mode (see enum atomisp_flash_mode) */ +#define V4L2_CID_FLASH_MODE (V4L2_CID_CAMERA_LASTP1 + 10) + +/* VCM slew control */ +#define V4L2_CID_VCM_SLEW (V4L2_CID_CAMERA_LASTP1 + 11) +/* VCM step time */ +#define V4L2_CID_VCM_TIMEING (V4L2_CID_CAMERA_LASTP1 + 12) + +/* Query Focus Status */ +#define V4L2_CID_FOCUS_STATUS (V4L2_CID_CAMERA_LASTP1 + 14) + +/* Query sensor's binning factor */ +#define V4L2_CID_BIN_FACTOR_HORZ (V4L2_CID_CAMERA_LASTP1 + 15) +#define V4L2_CID_BIN_FACTOR_VERT (V4L2_CID_CAMERA_LASTP1 + 16) + +/* number of frames to skip at stream start */ +#define V4L2_CID_G_SKIP_FRAMES (V4L2_CID_CAMERA_LASTP1 + 17) + +/* Query sensor's 2A status */ +#define V4L2_CID_2A_STATUS (V4L2_CID_CAMERA_LASTP1 + 18) +#define V4L2_2A_STATUS_AE_READY (1 << 0) +#define V4L2_2A_STATUS_AWB_READY (1 << 1) + +#define V4L2_CID_FMT_AUTO (V4L2_CID_CAMERA_LASTP1 + 19) + +#define V4L2_CID_RUN_MODE (V4L2_CID_CAMERA_LASTP1 + 20) +#define ATOMISP_RUN_MODE_VIDEO 1 +#define ATOMISP_RUN_MODE_STILL_CAPTURE 2 +#define ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE 3 +#define ATOMISP_RUN_MODE_PREVIEW 4 +#define ATOMISP_RUN_MODE_SDV 5 + +#define V4L2_CID_ENABLE_VFPP (V4L2_CID_CAMERA_LASTP1 + 21) +#define V4L2_CID_ATOMISP_CONTINUOUS_MODE (V4L2_CID_CAMERA_LASTP1 + 22) +#define V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE \ + (V4L2_CID_CAMERA_LASTP1 + 23) +#define V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER \ + (V4L2_CID_CAMERA_LASTP1 + 24) + +#define V4L2_CID_VFPP (V4L2_CID_CAMERA_LASTP1 + 25) +#define ATOMISP_VFPP_ENABLE 0 +#define ATOMISP_VFPP_DISABLE_SCALER 1 +#define ATOMISP_VFPP_DISABLE_LOWLAT 2 + +/* Query real flash status register value */ +#define V4L2_CID_FLASH_STATUS_REGISTER (V4L2_CID_CAMERA_LASTP1 + 26) + +#define V4L2_CID_START_ZSL_CAPTURE (V4L2_CID_CAMERA_LASTP1 + 28) +/* Lock and unlock raw buffer */ +#define V4L2_CID_ENABLE_RAW_BUFFER_LOCK (V4L2_CID_CAMERA_LASTP1 + 29) + +#define V4L2_CID_DEPTH_MODE (V4L2_CID_CAMERA_LASTP1 + 30) + +#define V4L2_CID_EXPOSURE_ZONE_NUM (V4L2_CID_CAMERA_LASTP1 + 31) +/* Disable digital zoom */ +#define V4L2_CID_DISABLE_DZ (V4L2_CID_CAMERA_LASTP1 + 32) + +#define V4L2_CID_TEST_PATTERN_COLOR_R (V4L2_CID_CAMERA_LASTP1 + 33) +#define V4L2_CID_TEST_PATTERN_COLOR_GR (V4L2_CID_CAMERA_LASTP1 + 34) +#define V4L2_CID_TEST_PATTERN_COLOR_GB (V4L2_CID_CAMERA_LASTP1 + 35) +#define V4L2_CID_TEST_PATTERN_COLOR_B (V4L2_CID_CAMERA_LASTP1 + 36) + +#define V4L2_BUF_FLAG_BUFFER_INVALID 0x0400 +#define V4L2_BUF_FLAG_BUFFER_VALID 0x0800 + +#define V4L2_BUF_TYPE_VIDEO_CAPTURE_ION (V4L2_BUF_TYPE_PRIVATE + 1024) + +#define V4L2_EVENT_ATOMISP_3A_STATS_READY (V4L2_EVENT_PRIVATE_START + 1) +#define V4L2_EVENT_ATOMISP_METADATA_READY (V4L2_EVENT_PRIVATE_START + 2) +#define V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE (V4L2_EVENT_PRIVATE_START + 3) +#define V4L2_EVENT_ATOMISP_ACC_COMPLETE (V4L2_EVENT_PRIVATE_START + 4) +#define V4L2_EVENT_ATOMISP_PAUSE_BUFFER (V4L2_EVENT_PRIVATE_START + 5) +#define V4L2_EVENT_ATOMISP_CSS_RESET (V4L2_EVENT_PRIVATE_START + 6) +/* Nonstandard color effects for V4L2_CID_COLORFX */ +enum { + V4L2_COLORFX_SKIN_WHITEN_LOW = 1001, + V4L2_COLORFX_SKIN_WHITEN_HIGH = 1002, + V4L2_COLORFX_WARM = 1003, + V4L2_COLORFX_COLD = 1004, + V4L2_COLORFX_WASHED = 1005, + V4L2_COLORFX_RED = 1006, + V4L2_COLORFX_GREEN = 1007, + V4L2_COLORFX_BLUE = 1008, + V4L2_COLORFX_PINK = 1009, + V4L2_COLORFX_YELLOW = 1010, + V4L2_COLORFX_PURPLE = 1011, +}; + +#endif /* _ATOM_ISP_H */ diff --git a/capturev4l2/atomisp_obj.cpp b/capturev4l2/atomisp_obj.cpp new file mode 100644 index 0000000..784d69c --- /dev/null +++ b/capturev4l2/atomisp_obj.cpp @@ -0,0 +1,37 @@ +#include "atomisp_obj.h" +#include +#include +#include +#include + +CAtomispObj::CAtomispObj(char *devName, io_method io, int saveFile, int cameraId, int ispMode): CV4l2Obj(devName, io, saveFile), m_cameraId(cameraId), m_ispMode(ispMode) +{ + +} + +int CAtomispObj::open_device(bool set_input) +{ + CV4l2Obj::open_device(); + + /* set ISP mode */ + struct v4l2_streamparm parm; + + /* set input */ + if (set_input && -1 == xioctl(VIDIOC_S_INPUT, &m_cameraId)) + errno_exit("VIDIOC_S_INPUT"); + + CLEAR(parm); + parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + parm.parm.capture.capturemode = m_ispMode; + if (-1 == xioctl(VIDIOC_S_PARM, &parm)) + errno_exit("VIDIOC_S_PARM"); + + return 0; +} + +void CAtomispObj::set_format(int width, int height, int format) +{ + m_width = width; + m_height = height; + m_format = format; +} diff --git a/capturev4l2/atomisp_obj.h b/capturev4l2/atomisp_obj.h new file mode 100644 index 0000000..4c78731 --- /dev/null +++ b/capturev4l2/atomisp_obj.h @@ -0,0 +1,16 @@ +#ifndef _ATOMISP_OBJ +#define _ATOMISP_OBJ + +#include "v4l2_obj.h" + +class CAtomispObj: public CV4l2Obj { +private: + int m_cameraId; + int m_ispMode; +public: + CAtomispObj(char *devName, io_method io, int saveFile, int cameraId, int ispMode); + int open_device(bool set_input = true); + void set_format(int width, int height, int format); +}; + +#endif diff --git a/capturev4l2/capture.cpp b/capturev4l2/capture.cpp new file mode 100644 index 0000000..8e18bcf --- /dev/null +++ b/capturev4l2/capture.cpp @@ -0,0 +1,1226 @@ +/* + * V4L2 video capture example + * + * This program can be used and distributed without restrictions. + */ + +#include +#include +#include +#include + +#include /* getopt_long() */ + +#include /* low-level i/o */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for videodev2.h */ + +#include + +#include "atomisp_obj.h" +#include "atomisp.h" +#include + +struct atomisp_loop { + class CAtomispObj *main; + class CAtomispObj *vf; + unsigned int loop; +}; + +struct time_profile { + struct timeval tv_start; + struct timeval tv_end; + unsigned int loop; + const char *proc_name; +}; + +static char *dev_name = NULL; +static io_method io = IO_METHOD_MMAP; + +/* ISP Specfic parameter */ +int horizontal_flip=0; +int vertical_flip=0; +static int cam_input = 0; /* Camera ID selection */ +static int main_width = 640; +static int main_height = 480; +static int main_format = V4L2_PIX_FMT_YUV420; +static int vf_width = 640; +static int vf_height = 480; +static int vf_format = V4L2_PIX_FMT_YUV420; +static int sdv_cap_width = 640; +static int sdv_cap_height = 480; +static int sdv_cap_format = V4L2_PIX_FMT_YUV420; +static int sdv_cap_vf_width = 640; +static int sdv_cap_vf_height = 480; +static int sdv_cap_vf_format = V4L2_PIX_FMT_YUV420; +static int zsl_cap_width = 640; +static int zsl_cap_height = 480; +static int zsl_cap_format = V4L2_PIX_FMT_YUV420; +static int zsl_cap_vf_width = 640; +static int zsl_cap_vf_height = 480; +static int zsl_cap_vf_format = V4L2_PIX_FMT_YUV420; +static int num_frame = 1; +static unsigned int sdv_cap_num_frame = 1; +static unsigned int zsl_cap_num_frame = 0; +static int dual_enable = 0; +static int saveFile = 1; +static int sub_stream = 0; +static int subdev_index = 0; +static int h_blank = -1; +static int v_blank = -1; +static int test_pattern = 0; +static int fps = 30; +#define MAX_STREAM_NUM 2 +#define ISP_MODE_PREVIEW 0x8000 +#define ISP_MODE_VIDEO 0x4000 +#define ISP_MODE_STILL 0x2000 +#define DBG_HV_BLANK 0x1000 +static int run_mode = ISP_MODE_PREVIEW; +static bool sdv = false; +static bool zsl = false; +static char *main_out_node[] = {"/dev/video0", "/dev/video5"}; +static char *post_out_node[] = {"/dev/video1", "/dev/video6"}; +static char *vf_out_node[] = {"/dev/video2", "/dev/video7"}; +static char *video_out_node[] = {"/dev/video3", "/dev/video8"}; + +char *format_to_str(int format); + +static void format_convert(char *s, int *dst) +{ +#define capture_format *dst + if (!strncmp(s, "RAW10", 5)) + capture_format = V4L2_PIX_FMT_SBGGR10; + if (!strncmp(s, "BGGR10", 6)) + capture_format = V4L2_PIX_FMT_SBGGR10; + if (!strncmp(s, "RGGB10", 6)) + capture_format = V4L2_PIX_FMT_SRGGB10; + if (!strncmp(s, "GRBG10", 6)) + capture_format = V4L2_PIX_FMT_SGRBG10; + if (!strncmp(s, "GBRG10", 6)) + capture_format = V4L2_PIX_FMT_SGBRG10; + if (!strncmp(s, "RAW8", 4)) + capture_format = V4L2_PIX_FMT_SRGGB8; + if (!strncmp(s, "BGGR8", 5)) + capture_format = V4L2_PIX_FMT_SBGGR8; + if (!strncmp(s, "RGGB8", 5)) + capture_format = V4L2_PIX_FMT_SRGGB8; + if (!strncmp(s, "GRBG8", 5)) + capture_format = V4L2_PIX_FMT_SGRBG8; + if (!strncmp(s, "GBRG8", 5)) + capture_format = V4L2_PIX_FMT_SGBRG8; + if (!strncmp(s, "YUV420", 6)) + capture_format = V4L2_PIX_FMT_YUV420; + if (!strncmp(s, "YVU420", 6)) + capture_format = V4L2_PIX_FMT_YVU420; + if (!strncmp(s, "YUV422", 6)) + capture_format = V4L2_PIX_FMT_YUV422P; + if (!strncmp(s, "YUV444", 6)) + capture_format = V4L2_PIX_FMT_YUV444; + if (!strncmp(s, "NV16", 4)) + capture_format = V4L2_PIX_FMT_NV16; + if (!strncmp(s, "NV61", 4)) + capture_format = V4L2_PIX_FMT_NV61; + if (!strncmp(s, "YUYV", 4)) + capture_format = V4L2_PIX_FMT_YUYV; + if (!strncmp(s, "UYVY", 4)) + capture_format = V4L2_PIX_FMT_UYVY; + if (!strncmp(s, "NV12", 4)) + capture_format = V4L2_PIX_FMT_NV12; + if (!strncmp(s, "NV21", 4)) + capture_format = V4L2_PIX_FMT_NV21; + if (!strncmp(s, "RGB565", 6)) + capture_format = V4L2_PIX_FMT_RGB565; + if (!strncmp(s, "RGB24", 5)) + capture_format = V4L2_PIX_FMT_RGB24; + if (!strncmp(s, "RGB32", 5)) + capture_format = V4L2_PIX_FMT_RGB32; +} + +static int capture_check_env(void) +{ + char *s = NULL; + + s = getenv("HFLIP"); + if (s != NULL) + horizontal_flip = atoi(s); + + s = getenv("VFLIP"); + if (s != NULL) + vertical_flip = atoi(s); + + s = getenv("INPUT"); + if (s != NULL) + cam_input = atoi(s); + + s = getenv("M_W"); + if (s != NULL) + main_width = atoi(s); + + s = getenv("M_H"); + if (s != NULL) + main_height = atoi(s); + + s = getenv("M_F"); + if (s !=NULL) + format_convert(s, &main_format); + + s = getenv("V_W"); + if (s != NULL) + vf_width = atoi(s); + + s = getenv("V_H"); + if (s != NULL) + vf_height = atoi(s); + + s = getenv("V_F"); + if (s !=NULL) + format_convert(s, &vf_format); + + s = getenv("SDV_W"); + if (s != NULL) + sdv_cap_width = atoi(s); + + s = getenv("SDV_H"); + if (s != NULL) + sdv_cap_height = atoi(s); + + s = getenv("SDV_F"); + if (s !=NULL) + format_convert(s, &sdv_cap_format); + + s = getenv("SDV_V_W"); + if (s != NULL) + sdv_cap_vf_width = atoi(s); + + s = getenv("SDV_V_H"); + if (s != NULL) + sdv_cap_vf_height = atoi(s); + + s = getenv("SDV_V_F"); + if (s !=NULL) + format_convert(s, &sdv_cap_vf_format); + + s = getenv("ZSL_W"); + if (s != NULL) + zsl_cap_width = atoi(s); + + s = getenv("ZSL_H"); + if (s != NULL) + zsl_cap_height = atoi(s); + + s = getenv("ZSL_F"); + if (s !=NULL) + format_convert(s, &zsl_cap_format); + + s = getenv("ZSL_V_W"); + if (s != NULL) + zsl_cap_vf_width = atoi(s); + + s = getenv("ZSL_V_H"); + if (s != NULL) + zsl_cap_vf_height = atoi(s); + + s = getenv("ZSL_V_F"); + if (s !=NULL) + format_convert(s, &zsl_cap_vf_format); + + s = getenv("C"); + if (s != NULL) + num_frame = atoi(s); + + s = getenv("SDV_C"); + if (s != NULL) + sdv_cap_num_frame = atoi(s); + + s = getenv("ZSL_C"); + if (s != NULL) + zsl_cap_num_frame = atoi(s); + + s = getenv("DUAL"); + if (s != NULL) + dual_enable = atoi(s); + + s = getenv("MODE"); + if (s != NULL) { + if (!strncmp(s, "STILL", 5)) + run_mode = ISP_MODE_STILL; + if (!strncmp(s, "PREVIEW", 7)) + run_mode = ISP_MODE_PREVIEW; + if (!strncmp(s, "VIDEO", 5)) + run_mode = ISP_MODE_VIDEO; + if (!strncmp(s, "HVBLANK", 5)) + run_mode = DBG_HV_BLANK; + if (!strncmp(s, "SDV", 3)) { + run_mode = ISP_MODE_VIDEO; + sdv = true; + } + if (!strncmp(s, "ZSL", 3)) { + run_mode = ISP_MODE_PREVIEW; + zsl = true; + } + } + + s = getenv("SAVE_FILE"); + if (s != NULL) + saveFile = atoi(s); + + s = getenv("STREAM"); + if (s != NULL) + sub_stream = atoi(s) % MAX_STREAM_NUM; + + s = getenv("SUBDEV"); + if (s != NULL) + subdev_index = atoi(s); + + s = getenv("VBLANK"); + if (s != NULL) + v_blank = atoi(s); + + s = getenv("HBLANK"); + if (s != NULL) + h_blank = atoi(s); + + s = getenv("TEST_PATTERN"); + if (s != NULL) + test_pattern = atoi(s); + + s = getenv("FPS"); + if (s != NULL) + fps = atoi(s); + + return 0; +} + +static void usage(FILE * fp, int argc, char **argv) +{ + (void)argc; + + fprintf(fp, + "Usage: %s [options]\n\n" + "Options:\n" + "-d | --device name Video device name [/dev/video]\n" + "-h | --help Print this message\n" + "-m | --mmap Use memory mapped buffers\n" + "-r | --read Use read() calls\n" + "-u | --userp Use application allocated buffers\n" + "HFLIP=1 Enable Horizontal Flip\n" + "VFLIP=1 Enable Vertical Flip\n" + "M_W= Main width\n" + "M_H= Main height\n" + "M_F= Main format\n" + " RAW10|RAW8|YUV420|YVU420|YUV422|YUV444\n" + " NV12|NV21|NV16|NV61|RBG565|RGB32\n" + "V_W= Viewfinder width\n" + "V_H= Viewfinder height\n" + "V_F= Viewfinder format\n" + " RAW10|RAW8|YUV420|YVU420|YUV422|YUV444\n" + " NV12|NV21|NV16|NV61|RBG565|RGB32\n" + "SDV_W= SDV main width\n" + "SDV_H= SDV main height\n" + "SDV_F= SDV main format\n" + " RAW10|RAW8|YUV420|YVU420|YUV422|YUV444\n" + " NV12|NV21|NV16|NV61|RBG565|RGB32\n" + "SDV_V_W= SDV capture viewfinder width\n" + "SDV_V_H= SDV capture viewfinder height\n" + "SDV_V_F= SDV capture viewfinder format\n" + " RAW10|RAW8|YUV420|YVU420|YUV422|YUV444\n" + " NV12|NV21|NV16|NV61|RBG565|RGB32\n" + "ZSL_W= ZSL main width\n" + "ZSL_H= ZSL main height\n" + "ZSL_F= ZSL main format\n" + " RAW10|RAW8|YUV420|YVU420|YUV422|YUV444\n" + " NV12|NV21|NV16|NV61|RBG565|RGB32\n" + "ZSL_V_W= ZSL capture viewfinder width\n" + "ZSL_V_H= ZSL capture viewfinder height\n" + "ZSL_V_F= ZSL capture viewfinder format\n" + " RAW10|RAW8|YUV420|YVU420|YUV422|YUV444\n" + " NV12|NV21|NV16|NV61|RBG565|RGB32\n" + "MODE= ISP running mode\n" + " PREIVEW|STILL|VIDEO|HVBLANK|SDV|ZSL\n" + "C= The number of frame to capture\n" + "SDV_C= The number of frame to SDV capture\n" + "ZSL_C= The number of frame to ZSL capture\n" + "DUAL= Enable dual output for STILL and VIDEO modes\n" + "SAVE_FILE= Enable image storing to file system\n" + "STREAM= Select stream ID for dual stream case\n" + "SUBDEV= subdev index\n" + "HBLANK= set h blank in num of pixels\n" + "VBLANK= set v blank in num of lines\n" + "FPS= set sensor fps\n" + "\n" + "Examples:\n" + "M_W=1920 M_H=1080 M_F=NV12 C=1 MODE=STILL DUAL=1 INPUT=0 capture_v4l2\n" + "M_W=1280 M_H=720 M_F=UYVY C=1 MODE=PREVIEW INPUT=1 capture_v4l2\n" + "M_W=960 M_H=720 M_F=NV12 C=10 ZSL_W=4160 ZSL_H=3104 ZSL_F=NV12 ZSL_V_W=640 ZSL_V_H=480 ZSL_V_F=NV12 ZSL_C=2 MODE=ZSL INPUT=0 capture_v4l2\n" + "", argv[0]); +} + +static const char short_options[] = "d:hmru"; + +static const struct option long_options[] = { + {"device", required_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {"mmap", no_argument, NULL, 'm'}, + {"read", no_argument, NULL, 'r'}, + {"userp", no_argument, NULL, 'u'}, + {0, 0, 0, 0} +}; + +static void process_basic_preview(); +static void process_basic_still(); +static void process_basic_video(); +static void process_sdv_video(); +static void process_zsl_preview(); +static int dbg_h_v_blank(void); + +int flip_control(class CAtomispObj & objControl, int hflip, int vflip){ + struct v4l2_control control; + int ret; + control.id = V4L2_CID_HFLIP; + control.value = hflip; + ret=objControl.xioctl(VIDIOC_S_CTRL, &control); + control.id = V4L2_CID_VFLIP; + control.value = vflip; + ret|=objControl.xioctl(VIDIOC_S_CTRL, &control); + return ret; +} + +int main(int argc, char **argv) +{ + for (;;) { + int index; + int c; + + c = getopt_long(argc, argv, short_options, long_options, + &index); + + if (-1 == c) + break; + + switch (c) { + case 0: /* getopt_long() flag */ + break; + + case 'd': + dev_name = optarg; + break; + + case 'h': + usage(stdout, argc, argv); + exit(EXIT_SUCCESS); + + case 'm': + io = IO_METHOD_MMAP; + break; + + case 'r': + io = IO_METHOD_READ; + break; + + case 'u': + io = IO_METHOD_USERPTR; + break; + + default: + usage(stderr, argc, argv); + exit(EXIT_FAILURE); + } + } + + /* Get Parameter for atomisp specfic parameter */ + capture_check_env(); + + switch (run_mode) { + case ISP_MODE_PREVIEW: + if (zsl) + process_zsl_preview(); + else + process_basic_preview(); + break; + case ISP_MODE_STILL: + process_basic_still(); + break; + case ISP_MODE_VIDEO: + if (sdv) + process_sdv_video(); + else + process_basic_video(); + break; + case DBG_HV_BLANK: + dbg_h_v_blank(); + break; + } + + exit(EXIT_SUCCESS); + + return 0; +} + +static void profile_start(struct time_profile *profile) +{ + gettimeofday(&profile->tv_start, NULL); +} + +static void profile_end(struct time_profile *profile) +{ + double time; + gettimeofday(&profile->tv_end, NULL); + time = profile->tv_end.tv_sec * 1000000.0 + profile->tv_end.tv_usec; + time -= profile->tv_start.tv_sec * 1000000.0 + profile->tv_start.tv_usec; + printf("%s: Time=%fms FPS=%f\n", profile->proc_name, time / 1000.0, + 1000000.0 * profile->loop / time); +} + +static void process_basic_preview() +{ + class CAtomispObj iAtomispObj(vf_out_node[sub_stream], io, saveFile, cam_input, run_mode); + int loop = num_frame; + struct time_profile profile; + struct v4l2_control control; + profile.loop = loop; + profile.proc_name = "Preview"; + + printf("Preview mode: %dx%d, %s.\n", main_width, main_height, + format_to_str(main_format)); + /* open main output */ + iAtomispObj.open_device(); + + /* Init device */ + iAtomispObj.set_format(main_width, main_height, main_format); + iAtomispObj.init_device(); + iAtomispObj.init_buffers(); + + /* Configure test pattern. */ + control.id = V4L2_CID_TEST_PATTERN; + control.value = test_pattern; + iAtomispObj.xioctl(VIDIOC_S_CTRL, &control); + + flip_control(iAtomispObj, horizontal_flip, vertical_flip); + /* start capture */ + iAtomispObj.start_capturing(); + + profile_start(&profile); + iAtomispObj.mainloop(loop); + profile_end(&profile); + + /* stop capture */ + iAtomispObj.stop_capturing(); + + /* Uninit device */ + iAtomispObj.uninit_device(); + + /* close device */ + iAtomispObj.close_device(); + +} +static void process_basic_still() +{ + class CAtomispObj iAtomispObj_main(main_out_node[sub_stream], io, saveFile, cam_input, run_mode); + class CAtomispObj iAtomispObj_vf(post_out_node[sub_stream], io, saveFile, cam_input, run_mode); + int loop = num_frame; + struct time_profile profile; + struct v4l2_control control; + profile.loop = loop; + profile.proc_name = "Still"; + + printf("Still mode: %dx%d, %s.\n", main_width, main_height, + format_to_str(main_format)); + + /* open main output */ + iAtomispObj_main.open_device(); + if (dual_enable) + iAtomispObj_vf.open_device(); + + /* Init device */ + iAtomispObj_main.set_format(main_width, main_height, main_format); + iAtomispObj_main.init_device(); + iAtomispObj_main.init_buffers(); + if (dual_enable) { + iAtomispObj_vf.set_format(vf_width, vf_height, vf_format); + iAtomispObj_vf.init_device(); + iAtomispObj_vf.init_buffers(); + } + + /* Configure test pattern. */ + control.id = V4L2_CID_TEST_PATTERN; + control.value = test_pattern; + iAtomispObj_main.xioctl(VIDIOC_S_CTRL, &control); + + flip_control(iAtomispObj_main, horizontal_flip, vertical_flip); + + /* start capture */ + profile_start(&profile); + if (!dual_enable) { + iAtomispObj_main.start_capturing(); + iAtomispObj_main.mainloop(loop); + } else { + iAtomispObj_main.start_capturing(); + iAtomispObj_vf.start_capturing(); + while (loop--) { + iAtomispObj_main.mainloop(1); + iAtomispObj_vf.mainloop(1); + } + } + profile_end(&profile); + + /* stop capture */ + iAtomispObj_main.stop_capturing(); + if (dual_enable) + iAtomispObj_vf.stop_capturing(); + + /* Uninit device */ + iAtomispObj_main.uninit_device(); + if (dual_enable) + iAtomispObj_vf.uninit_device(); + + /* close device */ + iAtomispObj_main.close_device(); + if (dual_enable) + iAtomispObj_vf.close_device(); +} +static void process_basic_video() +{ + class CAtomispObj iAtomispObj_main(video_out_node[sub_stream], io, saveFile, cam_input, run_mode); + class CAtomispObj iAtomispObj_vf(vf_out_node[sub_stream], io, saveFile, cam_input, run_mode); + int loop = num_frame; + struct time_profile profile; + struct v4l2_control control; + struct v4l2_streamparm parm; + + profile.loop = loop; + profile.proc_name = "Video"; + + printf("Video mode: %dx%d, %s.\n", main_width, main_height, + format_to_str(main_format)); + + /* open main output */ + iAtomispObj_main.open_device(); + if (dual_enable) + /* Don't set input since it will power cycle the sensor and + * wrong resolution table is selected. */ + iAtomispObj_vf.open_device(false); + + printf("Setting fps to %d\n", fps); + parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + parm.parm.capture.capturemode = CI_MODE_NONE; + parm.parm.capture.timeperframe.numerator = 1; + parm.parm.capture.timeperframe.denominator = fps; + iAtomispObj_main.xioctl(VIDIOC_S_PARM, &parm); + + /* Init device */ + iAtomispObj_main.set_format(main_width, main_height, main_format); + iAtomispObj_main.init_device(); + iAtomispObj_main.init_buffers(); + if (dual_enable) { + iAtomispObj_vf.set_format(vf_width, vf_height, vf_format); + iAtomispObj_vf.init_device(); + iAtomispObj_vf.init_buffers(); + } + + /* Configure test pattern. */ + control.id = V4L2_CID_TEST_PATTERN; + control.value = test_pattern; + iAtomispObj_main.xioctl(VIDIOC_S_CTRL, &control); + + flip_control(iAtomispObj_main, horizontal_flip, vertical_flip); + + /* start capture */ + profile_start(&profile); + if (!dual_enable) { + iAtomispObj_main.start_capturing(); + iAtomispObj_main.mainloop(loop); + } else { + iAtomispObj_main.start_capturing(); + iAtomispObj_vf.start_capturing(); + while (loop--) { + iAtomispObj_main.mainloop(1); + iAtomispObj_vf.mainloop(1); + } + } + profile_end(&profile); + + /* stop capture */ + iAtomispObj_main.stop_capturing(); + if (dual_enable) + iAtomispObj_vf.stop_capturing(); + + /* Uninit device */ + iAtomispObj_main.uninit_device(); + if (dual_enable) + iAtomispObj_vf.uninit_device(); + + /* close device */ + iAtomispObj_main.close_device(); + if (dual_enable) + iAtomispObj_vf.close_device(); +} + +void* frame_loop(void *ptr) +{ + struct atomisp_loop *atomisp = (struct atomisp_loop *)ptr; + while (atomisp->loop--) { + atomisp->main->mainloop(1); + if (atomisp->vf) + atomisp->vf->mainloop(1); + } + return NULL; +} + +static void process_sdv_video() +{ + struct v4l2_control control; + struct v4l2_ext_controls controls; + struct v4l2_ext_control ext_control; + struct v4l2_streamparm parm; + class CAtomispObj iAtomispObj_main(video_out_node[sub_stream], io, saveFile, cam_input, run_mode); + class CAtomispObj iAtomispObj_vf(vf_out_node[sub_stream], io, saveFile, cam_input, run_mode); + class CAtomispObj iAtomispObj_cap_main(main_out_node[sub_stream], io, saveFile, cam_input, run_mode); + class CAtomispObj iAtomispObj_cap_vf(post_out_node[sub_stream], io, saveFile, cam_input, run_mode); + pthread_t tid1, tid2; + struct atomisp_loop video_loop, capture_loop; + struct atomisp_cont_capture_conf capture_conf; + struct time_profile video_profile, capture_profile; + video_profile.proc_name = "Video+Preview"; + video_profile.loop = num_frame; + capture_profile.proc_name = "Capture+VF"; + capture_profile.loop = sdv_cap_num_frame; + + printf("SDV Video mode: %dx%d, %s.\n", main_width, main_height, + format_to_str(main_format)); + printf("SDV Capture mode: %dx%d, %s.\n", sdv_cap_width, sdv_cap_height, + format_to_str(sdv_cap_format)); + + /* open main output */ + iAtomispObj_main.open_device(); + iAtomispObj_vf.open_device(); + iAtomispObj_cap_main.open_device(); + iAtomispObj_cap_vf.open_device(); + + /* set ISP mode */ + memset(&parm, 0, sizeof(parm)); + parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + parm.parm.capture.capturemode = CI_MODE_PREVIEW; + iAtomispObj_cap_main.xioctl(VIDIOC_S_PARM, &parm); + parm.parm.capture.capturemode = run_mode; + iAtomispObj_cap_main.xioctl(VIDIOC_S_PARM, &parm); + + /* Init device */ + memset(&capture_conf, 0, sizeof(capture_conf)); + capture_conf.num_captures = (sdv_cap_num_frame ? sdv_cap_num_frame : 1); + capture_conf.skip_frames = 0; + capture_conf.offset = -1; + iAtomispObj_cap_main.xioctl(ATOMISP_IOC_S_CONT_CAPTURE_CONFIG, &capture_conf); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_MODE; + control.value = 1; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_MODE; + ext_control.value = 1; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE; + control.value = 5 + sdv_cap_num_frame; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE; + ext_control.value = 5 + sdv_cap_num_frame; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER; + control.value = 1; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER; + ext_control.value = 1; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + iAtomispObj_cap_main.set_format(sdv_cap_width, sdv_cap_height, sdv_cap_format); + iAtomispObj_cap_main.init_device(); + iAtomispObj_cap_vf.set_format(sdv_cap_vf_width, sdv_cap_vf_height, sdv_cap_vf_format); + iAtomispObj_cap_vf.init_device(); + + iAtomispObj_main.set_format(main_width, main_height, main_format); + iAtomispObj_main.init_device(); + iAtomispObj_vf.set_format(vf_width, vf_height, vf_format); + iAtomispObj_vf.init_device(); + + iAtomispObj_cap_main.init_buffers(); + iAtomispObj_cap_vf.init_buffers(); + iAtomispObj_main.init_buffers(); + iAtomispObj_vf.init_buffers(); + + /* Configure test pattern. */ + control.id = V4L2_CID_TEST_PATTERN; + control.value = test_pattern; + iAtomispObj_main.xioctl(VIDIOC_S_CTRL, &control); + + flip_control(iAtomispObj_main, horizontal_flip, vertical_flip); + + /* start capture */ + iAtomispObj_main.start_capturing(); + iAtomispObj_vf.start_capturing(); + profile_start(&video_profile); + iAtomispObj_main.mainloop(1); + iAtomispObj_vf.mainloop(1); + + video_loop.loop = num_frame - 1; + video_loop.main = &iAtomispObj_main; + video_loop.vf = &iAtomispObj_vf; + pthread_create(&tid1, NULL, frame_loop, &video_loop); + + if (sdv_cap_num_frame) { + capture_loop.loop = sdv_cap_num_frame; + capture_loop.main = &iAtomispObj_cap_main; + capture_loop.vf = &iAtomispObj_cap_vf; + iAtomispObj_cap_vf.start_capturing(); + profile_start(&capture_profile); + iAtomispObj_cap_main.start_capturing(); + pthread_create(&tid2, NULL, frame_loop, &capture_loop); + + pthread_join(tid2, NULL); + profile_end(&capture_profile); + /* stop capture */ + iAtomispObj_cap_main.stop_capturing(); + iAtomispObj_cap_vf.stop_capturing(); + } + + pthread_join(tid1, NULL); + profile_end(&video_profile); + + iAtomispObj_main.stop_capturing(); + iAtomispObj_vf.stop_capturing(); + + /* Uninit device */ + iAtomispObj_cap_main.uninit_device(); + iAtomispObj_cap_vf.uninit_device(); + iAtomispObj_main.uninit_device(); + iAtomispObj_vf.uninit_device(); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_MODE; + control.value = 0; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_MODE; + ext_control.value = 0; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE; + control.value = 0; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE; + ext_control.value = 0; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + /* close device */ + iAtomispObj_cap_main.close_device(); + iAtomispObj_cap_vf.close_device(); + iAtomispObj_main.close_device(); + iAtomispObj_vf.close_device(); +} + + +static void process_zsl_preview() +{ + struct v4l2_control control; + struct v4l2_ext_controls controls; + struct v4l2_ext_control ext_control; + struct v4l2_streamparm parm; + class CAtomispObj iAtomispObj_main(vf_out_node[sub_stream], io, saveFile, cam_input, run_mode); + class CAtomispObj iAtomispObj_cap_main(main_out_node[sub_stream], io, saveFile, cam_input, run_mode); + class CAtomispObj iAtomispObj_cap_vf(post_out_node[sub_stream], io, saveFile, cam_input, run_mode); + pthread_t tid1, tid2; + struct atomisp_loop preview_loop, capture_loop; + struct atomisp_cont_capture_conf capture_conf; + struct time_profile preview_profile, capture_profile; + preview_profile.proc_name = "Preview"; + preview_profile.loop = num_frame; + capture_profile.proc_name = "Capture+VF"; + capture_profile.loop = zsl_cap_num_frame; + + printf("ZSL preview mode: %dx%d, %s.\n", main_width, main_height, + format_to_str(main_format)); + printf("ZSL capture mode: %dx%d, %s, %dx%d, %s.\n", zsl_cap_width, + zsl_cap_height, format_to_str(zsl_cap_format), zsl_cap_vf_width, + zsl_cap_vf_height, format_to_str(zsl_cap_vf_format)); + + /* open main output */ + iAtomispObj_main.open_device(); + iAtomispObj_cap_main.open_device(); + iAtomispObj_cap_vf.open_device(); + + /* set ISP mode */ + memset(&parm, 0, sizeof(parm)); + parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + parm.parm.capture.capturemode = CI_MODE_PREVIEW; + iAtomispObj_cap_main.xioctl(VIDIOC_S_PARM, &parm); + + /* Init device */ + memset(&capture_conf, 0, sizeof(capture_conf)); + capture_conf.num_captures = (zsl_cap_num_frame ? zsl_cap_num_frame : 1); + capture_conf.skip_frames = 0; + capture_conf.offset = -1; + iAtomispObj_cap_main.xioctl(ATOMISP_IOC_S_CONT_CAPTURE_CONFIG, &capture_conf); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_MODE; + control.value = 1; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_MODE; + ext_control.value = 1; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE; + control.value = 5 + zsl_cap_num_frame; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE; + ext_control.value = 5 + zsl_cap_num_frame; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER; + control.value = 0; /* disable CVF */ + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER; + ext_control.value = 0; /* disable CVF */ + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + iAtomispObj_cap_main.set_format(zsl_cap_width, zsl_cap_height, zsl_cap_format); + iAtomispObj_cap_main.init_device(); + iAtomispObj_cap_vf.set_format(zsl_cap_vf_width, zsl_cap_vf_height, zsl_cap_vf_format); + iAtomispObj_cap_vf.init_device(); + + iAtomispObj_main.set_format(main_width, main_height, main_format); + iAtomispObj_main.init_device(); + + iAtomispObj_cap_main.init_buffers(); + iAtomispObj_cap_vf.init_buffers(); + iAtomispObj_main.init_buffers(); + + /* Configure test pattern. */ + control.id = V4L2_CID_TEST_PATTERN; + control.value = test_pattern; + iAtomispObj_main.xioctl(VIDIOC_S_CTRL, &control); + + flip_control(iAtomispObj_main, horizontal_flip, vertical_flip); + + /* start capture */ + iAtomispObj_main.start_capturing(); + profile_start(&preview_profile); + iAtomispObj_main.mainloop(1); + + preview_loop.loop = num_frame - 1; + preview_loop.main = &iAtomispObj_main; + preview_loop.vf = NULL; + pthread_create(&tid1, NULL, frame_loop, &preview_loop); + + if (zsl_cap_num_frame) { + capture_loop.loop = zsl_cap_num_frame; + capture_loop.main = &iAtomispObj_cap_main; + capture_loop.vf = &iAtomispObj_cap_vf; + iAtomispObj_cap_vf.start_capturing(); + profile_start(&capture_profile); + iAtomispObj_cap_main.start_capturing(); + pthread_create(&tid2, NULL, frame_loop, &capture_loop); + + pthread_join(tid2, NULL); + profile_end(&capture_profile); + /* stop capture */ + iAtomispObj_cap_main.stop_capturing(); + iAtomispObj_cap_vf.stop_capturing(); + } + + pthread_join(tid1, NULL); + profile_end(&preview_profile); + + iAtomispObj_main.stop_capturing(); + + /* Uninit device */ + iAtomispObj_cap_main.uninit_device(); + iAtomispObj_cap_vf.uninit_device(); + iAtomispObj_main.uninit_device(); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_MODE; + control.value = 0; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_MODE; + ext_control.value = 0; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + memset(&control, 0, sizeof(control)); + memset(&controls, 0, sizeof(controls)); + memset(&ext_control, 0, sizeof(ext_control)); + control.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE; + control.value = 0; + controls.ctrl_class = V4L2_CTRL_ID2CLASS(control.id); + controls.count = 1; + controls.controls = &ext_control; + ext_control.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE; + ext_control.value = 0; + iAtomispObj_cap_main.xioctl(VIDIOC_S_EXT_CTRLS, &controls); + iAtomispObj_cap_main.xioctl(VIDIOC_S_CTRL, &controls); + + /* close device */ + iAtomispObj_cap_main.close_device(); + iAtomispObj_cap_vf.close_device(); + iAtomispObj_main.close_device(); +} + + +static int dbg_h_v_blank(void) +{ + int fd; + char subdev[64]; + struct v4l2_control control; + struct v4l2_ext_controls ext_controls; + struct v4l2_ext_control ext_control; + unsigned long _pixel_rate; + int _h_blank; + int _v_blank; + int ret = 0; + + snprintf(subdev, 64, "/dev/v4l-subdev%d", subdev_index); + fd = open(subdev, O_RDWR /* required */ | O_NONBLOCK, 0); + + if (-1 == fd) { + fprintf(stderr, "Cannot open '%s': %d, %s\n", + subdev, errno, strerror(errno)); + exit(EXIT_FAILURE); + } + /* Get H Blank */ + control.id = V4L2_CID_HBLANK; + do + ret = ioctl(fd, VIDIOC_G_CTRL, &control); + while (-1 == ret && EINTR == errno); + if (!ret) { + _h_blank = control.value; + } else { + fprintf(stderr, "Failed to get H Blank: %d, %s\n", + errno, strerror(errno)); + goto end; + } + + /* Get V Blank */ + control.id = V4L2_CID_VBLANK; + do + ret = ioctl(fd, VIDIOC_G_CTRL, &control); + while (-1 == ret && EINTR == errno); + if (!ret) { + _v_blank = control.value; + } else { + fprintf(stderr, "Failed to get V Blank: %d, %s\n", + errno, strerror(errno)); + goto end; + } + /* Get Pixel Rate */ + ext_control.id = V4L2_CID_PIXEL_RATE; + ext_controls.ctrl_class = V4L2_CTRL_ID2CLASS(ext_control.id); + ext_controls.count = 1; + ext_controls.controls = &ext_control; + do + ret = ioctl(fd, VIDIOC_G_EXT_CTRLS, &ext_controls); + while (-1 == ret && EINTR == errno); + if (!ret) { + _pixel_rate = ext_control.value64; + } else { + printf("SUBDEV IOCTL:%d.\n", ret); + fprintf(stderr, "Failed to get Pixel rate: %d, %s\n", + errno, strerror(errno)); + goto end; + } + /* Calculate and Display H/V Blank time */ + printf("Get HBlank:%d, VBlank:%d, Pixel Rate: %ld.\n", + _h_blank, _v_blank, _pixel_rate); + /* Set New H/V Blank time if avaiable */ + /* Set H Blank */ + if (h_blank >= 0) { + control.id = V4L2_CID_HBLANK; + control.value = h_blank; + do + ret = ioctl(fd, VIDIOC_S_CTRL, &control); + while (-1 == ret && EINTR == errno); + if (!ret) { + if (!h_blank) + printf("Reset to original h_blank.\n"); + else + printf("Set New H Blank:%d.\n", control.value); + } else { + fprintf(stderr, "Failed to set H Blank: %d, %s\n", + errno, strerror(errno)); + goto end; + } + } + /* Set V Blank */ + if (v_blank >= 0) { + control.id = V4L2_CID_VBLANK; + control.value = v_blank; + do + ret = ioctl(fd, VIDIOC_S_CTRL, &control); + while (-1 == ret && EINTR == errno); + if (!ret) { + if (!v_blank) + printf("Reset to original v_blank.\n"); + else + printf("Set New V Blank:%d.\n", control.value); + } else { + fprintf(stderr, "Failed to set V Blank: %d, %s\n", + errno, strerror(errno)); + goto end; + } + } + +end: + close(fd); + return ret; + +} + +char *format_to_str(int format) +{ + switch (format) { + case V4L2_PIX_FMT_YUV420: + return (char*)"yuv420"; + case V4L2_PIX_FMT_YVU420: + return (char*)"yv12"; + case V4L2_PIX_FMT_YUV422P: + return (char*)"yuv422"; + case V4L2_PIX_FMT_YUV444: + return (char*)"yuv444"; + case V4L2_PIX_FMT_NV12: + return (char*)"nv12"; + case V4L2_PIX_FMT_NV21: + return (char*)"nv21"; + case V4L2_PIX_FMT_NV16: + return (char*)"nv16"; + case V4L2_PIX_FMT_NV61: + return (char*)"nv61"; + case V4L2_PIX_FMT_UYVY: + return (char*)"uyvy"; + case V4L2_PIX_FMT_YUYV: + return (char*)"yuyv"; + case V4L2_PIX_FMT_RGB565: + return (char*)"rgb565"; + case V4L2_PIX_FMT_RGB24: + return (char*)"rgb24"; + case V4L2_PIX_FMT_RGB32: + return (char*)"rgb32"; + case V4L2_PIX_FMT_SRGGB8: + return (char*)"rggb8"; + case V4L2_PIX_FMT_SGRBG8: + return (char*)"grbg8"; + case V4L2_PIX_FMT_SGBRG8: + return (char*)"gbrg8"; + case V4L2_PIX_FMT_SBGGR8: + return (char*)"bggr8"; + case V4L2_PIX_FMT_SRGGB10: + return (char*)"rggb10"; + case V4L2_PIX_FMT_SGRBG10: + return (char*)"grbg10"; + case V4L2_PIX_FMT_SGBRG10: + return (char*)"gbrg10"; + case V4L2_PIX_FMT_SBGGR10: + return (char*)"bggr10"; + default: + return (char*)"yuv420"; + } +} + +unsigned char format_to_bytes(int format) +{ + switch (format) { + case V4L2_PIX_FMT_YUV420: + return 1; + case V4L2_PIX_FMT_YVU420: + return 1; + case V4L2_PIX_FMT_YUV422P: + return 1; + case V4L2_PIX_FMT_YUV444: + return 3; + case V4L2_PIX_FMT_NV12: + return 1; + case V4L2_PIX_FMT_NV21: + return 1; + case V4L2_PIX_FMT_NV16: + return 1; + case V4L2_PIX_FMT_NV61: + return 1; + case V4L2_PIX_FMT_UYVY: + return 2; + case V4L2_PIX_FMT_YUYV: + return 2; + case V4L2_PIX_FMT_RGB565: + return 2; + case V4L2_PIX_FMT_RGB24: + return 3; + case V4L2_PIX_FMT_RGB32: + return 4; + case V4L2_PIX_FMT_SBGGR8: + return 1; + case V4L2_PIX_FMT_SRGGB10: + return 2; + case V4L2_PIX_FMT_SGRBG10: + return 2; + case V4L2_PIX_FMT_SGBRG10: + return 2; + case V4L2_PIX_FMT_SBGGR10: + return 2; + default: + return 1; + } +} diff --git a/capturev4l2/v4l2_obj.cpp b/capturev4l2/v4l2_obj.cpp new file mode 100644 index 0000000..b9cc63b --- /dev/null +++ b/capturev4l2/v4l2_obj.cpp @@ -0,0 +1,591 @@ +#include "v4l2_obj.h" +#include +#include +#include +#include + +#include /* getopt_long() */ + +#include /* low-level i/o */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for videodev2.h */ + +#include +#include +#include + +using namespace std; + +#include + +extern char *format_to_str(int format); +extern unsigned char format_to_bytes(int format); + +CV4l2Obj::CV4l2Obj (char *devName, io_method io, int saveFile): + m_devName(devName), m_io(io), m_saveFile(saveFile) +{ + m_width = 640; + m_height = 480; + m_format = V4L2_PIX_FMT_YUV420; + m_frameCnt = 0; + // m_saveFile = 0; +} + +int CV4l2Obj::init_device() +{ + struct v4l2_capability cap; + struct v4l2_cropcap cropcap; + struct v4l2_crop crop; + struct v4l2_format fmt; + + if (-1 == xioctl(VIDIOC_QUERYCAP, &cap)) { + if (EINVAL == errno) { + fprintf(stderr, "%s is no V4L2 device\n", m_devName); + exit(EXIT_FAILURE); + } else { + errno_exit("VIDIOC_QUERYCAP"); + } + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + fprintf(stderr, "%s is no video capture device\n", m_devName); + exit(EXIT_FAILURE); + } + + switch (m_io) { + case IO_METHOD_READ: + if (!(cap.capabilities & V4L2_CAP_READWRITE)) { + fprintf(stderr, "%s does not support read i/o\n", + m_devName); + exit(EXIT_FAILURE); + } + + break; + + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + fprintf(stderr, "%s does not support streaming i/o\n", + m_devName); + exit(EXIT_FAILURE); + } + + break; + } + + /* Select video input, video standard and tune here. */ + + CLEAR(cropcap); + + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (0 == xioctl(VIDIOC_CROPCAP, &cropcap)) { + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cropcap.defrect; /* reset to default */ + + if (-1 == xioctl(VIDIOC_S_CROP, &crop)) { + switch (errno) { + case EINVAL: + /* Cropping not supported. */ + break; + default: + /* Errors ignored. */ + break; + } + } + } else { + /* Errors ignored. */ + } + + CLEAR(fmt); + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = m_width; + fmt.fmt.pix.height = m_height; + fmt.fmt.pix.pixelformat = m_format; + fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + + if (-1 == xioctl(VIDIOC_S_FMT, &fmt)) + errno_exit("VIDIOC_S_FMT"); + + /* Note VIDIOC_S_FMT may change width and height. */ + m_width = fmt.fmt.pix.width; + m_height = fmt.fmt.pix.height; + m_format = fmt.fmt.pix.pixelformat; + m_padded_width = fmt.fmt.pix.bytesperline / format_to_bytes(m_format); + m_sizeimage = fmt.fmt.pix.sizeimage; + + printf("m_width %d, m_height %d, m_sizeimage %d, m_padded_width:%d, bytesperline %d\n", + m_width, m_height, m_sizeimage, m_padded_width, fmt.fmt.pix.bytesperline); + + return 0; +} + +int CV4l2Obj::init_buffers() +{ + switch (m_io) { + case IO_METHOD_READ: + return init_read(m_sizeimage); + + case IO_METHOD_MMAP: + return init_mmap(); + + case IO_METHOD_USERPTR: + return init_userp(m_sizeimage); + } + + return 0; +} + +int CV4l2Obj::uninit_device(void) +{ + unsigned int i; + + switch (m_io) { + case IO_METHOD_READ: + free(m_Buffers[0].start); + break; + + case IO_METHOD_MMAP: + for (i = 0; i < m_nBuffers; ++i) + if (-1 == munmap(m_Buffers[i].start, m_Buffers[i].length)) + errno_exit("munmap"); + break; + + case IO_METHOD_USERPTR: + for (i = 0; i < m_nBuffers; ++i) + free(m_Buffers[i].start); + break; + } + + free(m_Buffers); + + return 0; +} + +int CV4l2Obj::open_device() +{ + struct stat st; + + if (-1 == stat(m_devName, &st)) { + fprintf(stderr, "Cannot identify '%s': %d, %s\n", + m_devName, errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + if (!S_ISCHR(st.st_mode)) { + fprintf(stderr, "%s is no device\n", m_devName); + exit(EXIT_FAILURE); + } + + m_fd = open(m_devName, O_RDWR /* required */ | O_NONBLOCK, 0); + + if (-1 == m_fd) { + fprintf(stderr, "Cannot open '%s': %d, %s\n", + m_devName, errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + return 0; +} + +int CV4l2Obj::close_device() +{ + if (-1 == close(m_fd)) + errno_exit("close"); + + m_fd = -1; + + return 0; +} + +int CV4l2Obj::stop_capturing(void) +{ + enum v4l2_buf_type type; + + switch (m_io) { + case IO_METHOD_READ: + /* Nothing to do. */ + break; + + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (-1 == xioctl(VIDIOC_STREAMOFF, &type)) + errno_exit("VIDIOC_STREAMOFF"); + + break; + } + return 0; +} + +int CV4l2Obj::start_capturing(void) +{ + unsigned int i; + enum v4l2_buf_type type; + + switch (m_io) { + case IO_METHOD_READ: + /* Nothing to do. */ + break; + + case IO_METHOD_MMAP: + for (i = 0; i < m_nBuffers; ++i) { + struct v4l2_buffer buf; + + CLEAR(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (-1 == xioctl(VIDIOC_QBUF, &buf)) + errno_exit("VIDIOC_QBUF"); + } + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (-1 == xioctl(VIDIOC_STREAMON, &type)) + errno_exit("VIDIOC_STREAMON"); + + break; + + case IO_METHOD_USERPTR: + for (i = 0; i < m_nBuffers; ++i) { + struct v4l2_buffer buf; + + CLEAR(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = i; + buf.m.userptr = (unsigned long)m_Buffers[i].start; + buf.length = m_Buffers[i].length; + + if (-1 == xioctl(VIDIOC_QBUF, &buf)) + errno_exit("VIDIOC_QBUF"); + } + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (-1 == xioctl(VIDIOC_STREAMON, &type)) + errno_exit("VIDIOC_STREAMON"); + + break; + } + return 0; +} + +int CV4l2Obj::mainloop(unsigned int count) +{ + while (count-- > 0) { + for (;;) { + fd_set fds; + struct timeval tv; + int r; + + FD_ZERO(&fds); + FD_SET(m_fd, &fds); + + /* Timeout. */ + tv.tv_sec = 4; + tv.tv_usec = 0; + + r = select(m_fd + 1, &fds, NULL, NULL, &tv); + + if (-1 == r) { + if (EINTR == errno) + continue; + + errno_exit("select"); + } + + if (0 == r) { + fprintf(stderr, "select timeout\n"); + exit(EXIT_FAILURE); + } + + if (read_frame()) + break; + + /* EAGAIN - continue select loop. */ + } + } + return 0; +} + +int CV4l2Obj::init_read(unsigned int buffer_size) +{ + m_Buffers = (struct Buffer*)calloc(1, sizeof(*m_Buffers)); + + if (!m_Buffers) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } + + m_Buffers[0].length = buffer_size; + m_Buffers[0].start = malloc(buffer_size); + + if (!m_Buffers[0].start) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } + return 0; +} + +int CV4l2Obj::init_mmap(void) +{ + struct v4l2_requestbuffers req; + + CLEAR(req); + + req.count = 4; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + + if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { + if (EINVAL == errno) { + fprintf(stderr, "%s does not support " + "memory mapping\n", m_devName); + exit(EXIT_FAILURE); + } else { + errno_exit("VIDIOC_REQBUFS"); + } + } + + if (req.count < 2) { + fprintf(stderr, "Insufficient buffer memory on %s\n", m_devName); + exit(EXIT_FAILURE); + } + + m_Buffers = (struct Buffer*)calloc(req.count, sizeof(*m_Buffers)); + + if (!m_Buffers) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } + + for (m_nBuffers = 0; m_nBuffers < req.count; ++m_nBuffers) { + struct v4l2_buffer buf; + + CLEAR(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = m_nBuffers; + + if (-1 == xioctl(VIDIOC_QUERYBUF, &buf)) + errno_exit("VIDIOC_QUERYBUF"); + + m_Buffers[m_nBuffers].length = buf.length; + m_Buffers[m_nBuffers].start = mmap(NULL /* start anywhere */ , + buf.length, + PROT_READ | PROT_WRITE + /* required */ , + MAP_SHARED /* recommended */ , + m_fd, buf.m.offset); + + if (MAP_FAILED == m_Buffers[m_nBuffers].start) + errno_exit("mmap"); + } + return 0; +} + +int CV4l2Obj::init_userp(unsigned int buffer_size) +{ + struct v4l2_requestbuffers req; + unsigned int page_size; + + page_size = getpagesize(); + buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1); + + CLEAR(req); + + req.count = 4; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_USERPTR; + + if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { + if (EINVAL == errno) { + fprintf(stderr, "%s does not support " + "user pointer i/o\n", m_devName); + exit(EXIT_FAILURE); + } else { + errno_exit("VIDIOC_REQBUFS"); + } + } + + m_Buffers = (struct Buffer*)calloc(4, sizeof(*m_Buffers)); + + if (!m_Buffers) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } + + for (m_nBuffers = 0; m_nBuffers < 4; ++m_nBuffers) { + m_Buffers[m_nBuffers].length = buffer_size; + m_Buffers[m_nBuffers].start = memalign( /* boundary */ page_size, + buffer_size); + + if (!m_Buffers[m_nBuffers].start) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } + } + return 0; +} + +int CV4l2Obj::xioctl(int request, void *arg) +{ + int r; + + do + r = ioctl(m_fd, request, arg); + while (-1 == r && EINTR == errno); + + return r; +} + +int CV4l2Obj::read_frame(void) +{ + struct v4l2_buffer buf; + unsigned int i; + + switch (m_io) { + case IO_METHOD_READ: + if (-1 == read(m_fd, m_Buffers[0].start, m_Buffers[0].length)) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + errno_exit("read"); + } + } + + process_image(m_Buffers[0].start, m_Buffers[0].length); + + break; + + case IO_METHOD_MMAP: + CLEAR(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (-1 == xioctl(VIDIOC_DQBUF, &buf)) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + errno_exit("VIDIOC_DQBUF"); + } + } + + assert(buf.index < m_nBuffers); + + process_image(m_Buffers[buf.index].start, m_Buffers[buf.index].length); + + if (-1 == xioctl(VIDIOC_QBUF, &buf)) + errno_exit("VIDIOC_QBUF"); + + break; + + case IO_METHOD_USERPTR: + CLEAR(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + + if (-1 == xioctl(VIDIOC_DQBUF, &buf)) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + errno_exit("VIDIOC_DQBUF"); + } + } + + for (i = 0; i < m_nBuffers; ++i) + if (buf.m.userptr == (unsigned long)m_Buffers[i].start + && buf.length == m_Buffers[i].length) + break; + + assert(i < m_nBuffers); + + process_image((void *)buf.m.userptr, buf.length); + + if (-1 == xioctl(VIDIOC_QBUF, &buf)) + errno_exit("VIDIOC_QBUF"); + + break; + } + + return 1; +} + +int CV4l2Obj::process_image(const void *p, int size) +{ + if (m_saveFile) { + ostringstream sFileName; + ofstream fp; + char *buf = (char *)p; + char *s_format = format_to_str(m_format);; + char *prefix = strstr(m_devName, "video"); + + if (!buf) { + cout << "Invalid buffer address!" << endl; + exit(0); + } + + sFileName << "Image-" << prefix << "-" << m_padded_width << "x" << m_height << "-" << m_frameCnt << "." << s_format; + cout << "Saving file: " << sFileName.str().c_str() << endl; + + fp.open(sFileName.str().c_str()); + + if (!fp) { + cout << "Open file: " << sFileName.str().c_str() << " failed" << endl; + exit(0); + } + + fp.write(buf, size); + + fp.close(); + } + + m_frameCnt++; + return 0; +} + +void CV4l2Obj::errno_exit(const char *s) +{ + fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno)); + + exit(EXIT_FAILURE); +} diff --git a/capturev4l2/v4l2_obj.h b/capturev4l2/v4l2_obj.h new file mode 100644 index 0000000..5bd6a7b --- /dev/null +++ b/capturev4l2/v4l2_obj.h @@ -0,0 +1,59 @@ +#ifndef _V4L2_OBJ +#define _V4L2_OBJ + +#include +#include + +#define CLEAR(x) memset(&(x), 0, sizeof(x)) + +typedef enum { + IO_METHOD_READ, + IO_METHOD_MMAP, + IO_METHOD_USERPTR, +} io_method; + +class CV4l2Obj { + +private: + char *m_devName; + io_method m_io; + struct Buffer { + void *start; + size_t length; + }; + struct Buffer *m_Buffers; + unsigned int m_nBuffers; + + int m_frameCnt; + + int m_saveFile; +protected: + int m_width; + int m_padded_width; + int m_height; + int m_format; + int m_sizeimage; +public: + CV4l2Obj(char *devName, io_method io, int saveFile); + int stop_capturing(void); + int start_capturing(void); + int uninit_device(void); + int init_device(void); + int init_buffers(void); + int open_device(void); + int close_device(void); + int mainloop(unsigned int count); + int xioctl(int request, void *arg); + + int m_fd; +private: + int init_read(unsigned int buffer_size); + int init_mmap(void); + int init_userp(unsigned int buffer_size); +protected: + int read_frame(void); + int process_image(const void *p, int size); + + void errno_exit(const char *s); +}; +#endif