Hello everyone,
I'm trying to convert bayer image from CMOS sensor (MT9P031) to raw UYVY format (well, at least) in single-shot previewer mode on DM355. The main problem is: currently I've got no access to the working device (dm355 + sensor on one board), only like separate devices. I'm only able to connect the sensor to PC and use special utility to get image from the sensor. Thus, there is no 100% guarantee that the image received is the same as the one I would capture with sensor on working board. Then try to convert this image to UYVY on DM355 board.
Anyway, currently I've got two questions regarding color conversion and ipipe:
1. While I've read a lot of papers/datasheets and whatnot, I'm still not sure how bayer format should be presented for ipipe. What kind of data should I expect from sensor? Is it 48 bit format (12bit R + 12bit B + 12bit G + 12bit G) or 64bit (four 12bit subpixels, each in its own 16bit space)? Big endian or little endian?
2. When I'm trying to set params for RGB-YCbCr conversion previewer module as following:
struct prev_rgb2yuv rgb2yuv_params = { // S12Q8 (from do_preview_resize example for dm365) .coef_ry = { 0, 77}, //.coef_ry = { 1, 250}, .coef_gy = { 0, 150}, //.coef_gy = { 1, 150}, .coef_by = { 0, 29}, .coef_rcb = { ((-43 & 0xF00) >> 8), (-43 & 0xFF)}, .coef_gcb = { ((-85 & 0xF00) >> 8), (-85 & 0xFF)}, .coef_bcb = { 0, 128}, .coef_rcr = { 0, 128}, .coef_gcr = { ((-107 & 0xF00) >> 8), (-107 & 0xFF)}, .coef_bcr = { ((-21 & 0xF00) >> 8), (-21 & 0xFF)}, // S11 .out_ofst_y = 0, .out_ofst_cb = 128, .out_ofst_cr = 128 };
I end up with error on PREV_S_PARAM ioctl call. Is there something wrong with these params? Parameters for other modules (like YUV422 conversion) work ok. Should I set something else?
Also, I tried to get default params straight from module itself, but PREV_G_PARAM ioctl call (look in source file) is not seems to be working.
I'll be glad to hear any suggestions and/or advices, thank you.
Header and source file:
try_ipipe.h:
#define INBUFSNUM 1 #define OUTBUFSNUM 1 unsigned int preview_fd, oper_mode, user_mode; int ret, expected_size, size, i, outwidth, outheight, outsize; unsigned int *input_buffer, *output_buffer; struct prev_channel_config prev_chan_par; struct prev_single_shot_config prev_ss_config; struct prev_cap cap; struct prev_module_param mod_param; struct imp_reqbufs reqbuf_params; struct imp_buffer inbuf_params[INBUFSNUM], outbuf_params[OUTBUFSNUM]; struct imp_convert conv_params; //struct prev_rgb2yuv yuv_test_str; //struct prev_rgb2yuv rgb2yuv_params; FILE *infile, *outfile; /*********************************************************************** * RGB2YUV config params ***********************************************************************/ //static char en_rgb2yuv; struct prev_rgb2yuv rgb2yuv_params = { // S12Q8 .coef_ry = { 0, 77}, //.coef_ry = { 1, 250}, .coef_gy = { 0, 150}, //.coef_gy = { 1, 150}, .coef_by = { 0, 29}, .coef_rcb = { ((-43 & 0xF00) >> 8), (-43 & 0xFF)}, .coef_gcb = { ((-85 & 0xF00) >> 8), (-85 & 0xFF)}, .coef_bcb = { 0, 128}, .coef_rcr = { 0, 128}, .coef_gcr = { ((-107 & 0xF00) >> 8), (-107 & 0xFF)}, .coef_bcr = { ((-21 & 0xF00) >> 8), (-21 & 0xFF)}, // S11 .out_ofst_y = 0, .out_ofst_cb = 128, .out_ofst_cr = 128 }; static struct prev_yuv422_conv yuv422_params = { .en_chrom_lpf = 1, .chrom_pos = IPIPE_YUV422_CHR_POS_COSITE };
try_ipipe.c:
#include <stdio.h> #include <media/davinci/dm355_ipipe.h> #include <media/davinci/imp_previewer.h> #include <sys/ioctl.h> #include <stdlib.h> #include <media/davinci/imp_common.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "try_ipipe.h" #include <string.h> #include <sys/mman.h> int main(int argc, const char* argv[]) { const char *input_name, *output_name; int width, height, input_bpp, output_bpp; if(argc < 6) { // usage report if parameters are not properly set printf("Command-line: try_ipipe <width> <height> <input_bpp> <output_bpp> <input_file> <output_file>"); //exit(0); return 0; } else { width = atoi(argv[1]); height = atoi(argv[2]); input_bpp = atoi(argv[3]); output_bpp = atoi(argv[4]); input_name = argv[5]; output_name = argv[6]; } // opening previewer device printf("Opening previewer\n"); preview_fd = open("/dev/davinci_previewer", O_RDWR); if (preview_fd <= 0) { perror("Cannot open previewer device\n"); return -1; } // opening input file printf("Opening input file\n"); infile = fopen(input_name, "rb"); if (infile == NULL) { printf("Error in opening input file\n"); close(preview_fd); return -1; } // do we get input file of expected size (means bpp is ok) expected_size = width * height * input_bpp; fseek(infile, 0, SEEK_END); size = ftell(infile); rewind(infile); if (size != expected_size) { printf("Expected and actual size of input file does not match. Size is %i, expected size is %i\n", size, expected_size); close(preview_fd); return -1; } printf("File's size is %u bytes as expected. \n",size); // previewer mode user_mode = IMP_MODE_SINGLE_SHOT; // trying to set the mode printf("Setting previewer operation mode...\n"); if (ioctl(preview_fd, PREV_S_OPER_MODE, &user_mode) < 0) { perror("Can't set operation mode\n"); close(preview_fd); return -1; } // got it? printf("Checking previewer operation mode\n"); if (ioctl(preview_fd, PREV_G_OPER_MODE, &oper_mode) < 0) { perror("Can't get operation mode\n"); close(preview_fd); return -1; } if (oper_mode != user_mode) { printf("Cant set the previewer operation mode, tried to set user_mode=%i, but previwer returned oper_mode=%i\n", user_mode, oper_mode); close(preview_fd); return -1; } else { printf("Previewer operation mode set successfully. oper_mode=%i, user_mode=%i\n", oper_mode, user_mode); } // trying to configure the previewer // initizlizing default settings prev_chan_par.oper_mode = oper_mode; prev_chan_par.len = 0; prev_chan_par.config = NULL; if (ioctl(preview_fd, PREV_S_CONFIG, &prev_chan_par) < 0) { perror("Error in setting default configuration\n"); close(preview_fd); return -1; } printf("Previewer successfully configured with default settings.\n"); // configuring previewer for corresponding mode prev_chan_par.oper_mode = oper_mode; prev_chan_par.len = sizeof(struct prev_single_shot_config); prev_chan_par.config = &prev_ss_config; // loading current settings from module (default settings) if (ioctl(preview_fd, PREV_G_CONFIG, &prev_chan_par) < 0) { perror("Can't get previewer configuration\n"); close(preview_fd); return -1; } // changing what needs to be changed prev_chan_par.oper_mode = oper_mode; prev_chan_par.len = sizeof(struct prev_single_shot_config); prev_chan_par.config = &prev_ss_config; // prev_ss_config.bypass = IPIPE_BYPASS_ON; // prev_ss_input_spec prev_ss_config.input.image_width = width; prev_ss_config.input.image_height = height; prev_ss_config.input.ppln = prev_ss_config.input.image_width + 8; prev_ss_config.input.lpfr = prev_ss_config.input.image_height + 10; //prev_ss_config.input.line_length = 1; // could be anything, but probably 1 //printf("Line length = %d\n", prev_ss_config.input.line_length); /* if (input_std_params.scan_width >= 1280) { prev_ss_config.input.dec_en = 1; prev_ss_config.input.rsz = input_std_params.scan_width * 16 / 1280; } */ // bayer colors format: prev_ss_config.input.colp_olep = IPIPE_BLUE; prev_ss_config.input.colp_olop = IPIPE_GREEN_BLUE; prev_ss_config.input.colp_elep = IPIPE_GREEN_RED; prev_ss_config.input.colp_elop = IPIPE_RED; // ipipe conversion formats: /* ~/dvsdk/git/drivers/char/dm355_ipipe.c: IPIPE_RAW2RAW: IPIPE_BAYER_8BIT_PACK -> IPIPE_BAYER IPIPE_BAYER_8BIT_PACK_ALAW -> IPIPE_BAYER IPIPE_BAYER -> IPIPE_BAYER IPIPE_RAW2YUV: IPIPE_BAYER_8BIT_PACK -> IPIPE_UYVY IPIPE_BAYER_8BIT_PACK_ALAW -> IPIPE_UYVY IPIPE_BAYER -> IPIPE_UYVY IPIPE_YUV2YUV: IPIPE_UYVY -> IPIPE_UYVY */ prev_ss_config.input.pix_fmt = IPIPE_BAYER; // prev_ss_config.input.pix_fmt = IPIPE_UYVY; prev_ss_config.input.data_shift = IPIPEIF_BITS11_0; prev_ss_config.output.pix_fmt = IPIPE_UYVY; printf("Configuring previewer\n"); // loading modified settings back to the driver if (ioctl(preview_fd, PREV_S_CONFIG, &prev_chan_par) < 0) { perror("Can't set previewer configuration\n"); close(preview_fd); return -1; } // trying to reread the config and check if everything is alright bzero(&prev_ss_config, sizeof(struct prev_single_shot_config)); if (ioctl(preview_fd, PREV_G_CONFIG, &prev_chan_par) < 0) { perror("Can't get previewer configuration\n"); close(preview_fd); return -1; } else if(prev_ss_config.output.pix_fmt != IPIPE_UYVY) { perror("Driver configuration was unsuccessfull\n"); close(preview_fd); return -1; } printf ("New previewer settings loaded.\n"); // initializing ipipe modules with cap.index = 0; while (ioctl(preview_fd, PREV_ENUM_CAP, &cap) == 0) { strcpy(mod_param.version, cap.version); mod_param.module_id = cap.module_id; printf("Setting default for %s\n", cap.module_name); mod_param.param = NULL; // setting default params if (ioctl(preview_fd, PREV_S_PARAM, &mod_param)<0) { perror("Error in Setting default module params\n"); close(preview_fd); return -1; } if (cap.module_id == PREV_RGB2YUV) { if (ioctl(preview_fd, PREV_G_PARAM, &mod_param) < 0) { printf("Error in getting default settings for %s\n", cap.module_name); //close(preview_fd); //return -1; } else if(mod_param.param != NULL) { printf("Default settings for %s:\n", cap.module_name); printf("mod_param.len=%zu\n", mod_param.len); //&rgb2yuv_params = &mod_param.param; if(mod_param.len == sizeof(struct prev_rgb2yuv)) { memcpy(&rgb2yuv_params, &mod_param.param, mod_param.len); printf("rgb2yuv_param.coef_ry = {0x%x, 0x%x}\n", rgb2yuv_params.coef_ry.integer, rgb2yuv_params.coef_ry.decimal); printf("rgb2yuv_param.coef_gy = {0x%x, 0x%x}\n", rgb2yuv_params.coef_gy.integer, rgb2yuv_params.coef_gy.decimal); printf("rgb2yuv_param.coef_by = {0x%x, 0x%x}\n", rgb2yuv_params.coef_by.integer, rgb2yuv_params.coef_by.decimal); printf("rgb2yuv_param.coef_rcb = {0x%x, 0x%x}\n", rgb2yuv_params.coef_rcb.integer, rgb2yuv_params.coef_rcb.decimal); printf("rgb2yuv_param.coef_gcb = {0x%x, 0x%x}\n", rgb2yuv_params.coef_gcb.integer, rgb2yuv_params.coef_gcb.decimal); printf("rgb2yuv_param.coef_bcb = {0x%x, 0x%x}\n", rgb2yuv_params.coef_bcb.integer, rgb2yuv_params.coef_bcb.decimal); printf("rgb2yuv_param.coef_rcr = {0x%x, 0x%x}\n", rgb2yuv_params.coef_rcr.integer, rgb2yuv_params.coef_rcr.decimal); printf("rgb2yuv_param.coef_gcr = {0x%x, 0x%x}\n", rgb2yuv_params.coef_gcr.integer, rgb2yuv_params.coef_gcr.decimal); printf("rgb2yuv_param.coef_bcr = {0x%x, 0x%x}\n", rgb2yuv_params.coef_bcr.integer, rgb2yuv_params.coef_bcr.decimal); printf("rgb2yuv_param.out_ofst_y = %x\n", rgb2yuv_params.out_ofst_y); printf("rgb2yuv_param.out_ofst_cb = %x\n", rgb2yuv_params.out_ofst_cb); printf("rgb2yuv_param.out_ofst_cr = %x\n", rgb2yuv_params.out_ofst_cr); } } else { perror("mod_param.param == NULL\n"); close(preview_fd); return -1; } mod_param.len = sizeof(struct prev_rgb2yuv); mod_param.param = &rgb2yuv_params; } if (cap.module_id == PREV_YUV422_CONV) { mod_param.len = sizeof(struct prev_yuv422_conv); mod_param.param = &yuv422_params; } if (ioctl(preview_fd, PREV_S_PARAM, &mod_param)<0) { perror("Error in Setting module special params\n"); close(preview_fd); return -1; } cap.index++; } printf("All modules are set.\n"); printf("Previewer initialization complete.\n"); // buffers handling // input buffer printf("requesting and querring appropiate buffers\n"); reqbuf_params.buf_type = IMP_BUF_IN; reqbuf_params.size = size; reqbuf_params.count = INBUFSNUM; if (ioctl(preview_fd, PREV_REQBUF, &reqbuf_params) < 0) { perror("Error in PREV_REQBUF for IMP_BUF_IN\n"); close(preview_fd); return -1; } for (i = 0; i < INBUFSNUM; i++) { inbuf_params[i].index=i; inbuf_params[i].buf_type=IMP_BUF_IN; if (ioctl(preview_fd, PREV_QUERYBUF, &inbuf_params[i]) < 0) { perror("Error in PREV_QUERYBUF for IMP_BUF_IN\n"); close(preview_fd); return -1; } } // output buffer outwidth = width; outheight = height; outwidth += 15; outwidth &= (~15); outsize = outwidth * outheight * output_bpp; reqbuf_params.buf_type = IMP_BUF_OUT1; reqbuf_params.size = outsize; reqbuf_params.count = OUTBUFSNUM; if (ioctl(preview_fd, PREV_REQBUF, &reqbuf_params) < 0) { perror("Error in PREV_REQBUF for IMP_BUF_IN\n"); close(preview_fd); return -1; } for (i = 0; i < OUTBUFSNUM; i++) { outbuf_params[i].index = i; outbuf_params[i].buf_type = IMP_BUF_OUT1; if (ioctl(preview_fd, PREV_QUERYBUF, &outbuf_params[i]) < 0) { perror("Error in PREV_QUERBUF for IMP_BUF_OUT1\n"); close(preview_fd); return -1; } } // buffers are set, trying to map them printf("inbuf_params.offset = %08x, inbuf_params.size = %i\n", inbuf_params[0].offset, inbuf_params[0].size); input_buffer = mmap(NULL, inbuf_params[0].size, PROT_READ|PROT_WRITE, MAP_SHARED, preview_fd, inbuf_params[0].offset); if (input_buffer == MAP_FAILED) { perror("Error in MMAP\n"); close(preview_fd); return -1; } printf("outbuf_params.offset = %08x, outbuf_params.size = %i\n", outbuf_params[0].offset, outbuf_params[0].size); output_buffer = mmap(NULL,outbuf_params[0].size, PROT_READ|PROT_WRITE, MAP_SHARED, preview_fd, inbuf_params[0].offset); if (output_buffer == MAP_FAILED) { perror("Error in MMAP\n"); close(preview_fd); return -1; } printf("Buffer requests and queries fullfilled\n"); // buffers are ready and mapped, lets get to work // zeroing previwer params, just in case bzero(&conv_params, sizeof(conv_params)); // filling up previewer params // input buffers: conv_params.in_buff.index = 0; conv_params.in_buff.buf_type = IMP_BUF_IN; conv_params.in_buff.offset = inbuf_params[0].offset; conv_params.in_buff.size = inbuf_params[0].size; // output buffers: conv_params.out_buff1.index = 0; conv_params.out_buff1.buf_type = IMP_BUF_OUT1; conv_params.out_buff1.offset = outbuf_params[0].offset; conv_params.out_buff1.size = outbuf_params[0].size; // main part: printf("Starting preview\n"); // reading input file: fread(input_buffer, input_bpp, size/input_bpp, infile); // runnin previewer if (ioctl(preview_fd, PREV_PREVIEW, &conv_params) < 0) { perror("Error in doing preview\n"); munmap(input_buffer, inbuf_params[0].size); munmap(output_buffer, outbuf_params[0].size); close(preview_fd); return -1; } // operation completed, we've got our image in output buffer printf("Finishing preview. Trying to create output file...\n"); // writing output file outfile = fopen(output_name, "wb"); if (outfile == NULL) { perror("Error while trying to open output file\n"); munmap(input_buffer, inbuf_params[0].size); munmap(output_buffer, outbuf_params[0].size); close(preview_fd); return -1; } printf("Writing output...\n"); if (fwrite(output_buffer, 1, outsize, outfile) != outsize) { perror("Error: writing to output file\n"); munmap(input_buffer, inbuf_params[0].size); munmap(output_buffer, outbuf_params[0].size); close(preview_fd); return -1; } printf("Output written, time for memory cleanup...\n"); // freeing memory munmap(input_buffer, inbuf_params[0].size); munmap(output_buffer, outbuf_params[0].size); // closing files fclose(infile); fclose(outfile); // closing previewer handle close(preview_fd); printf("Finished!\n"); return 0; }