1. 概述
mipi csi规范中为了在mipi 传输中节约带宽采用所谓紧密存储格式,这样的格式虽然在传输中节约了带宽,可是这样的格式若想在调试中显示却未必是好的选择,之所以说未必是因为笔者的工具里是不能直接显示这样的格式,但有没有其它什么工具可以直接显示,笔者不是很清楚,不能显示也无妨,这样的转换并不复杂。
如需显示需要对mipi raw 进行打包, 把mipi raw的字节打包重组成像素。
也许有人会问mipi csi 的数据为何不直接给isp处理而要经过DDR中转,
这个就是如今常说的offline pipeline mode, 直接给ISP处理我们就称之为online pipiline mode,
那为何要采用offline mode, offline mode 明显看起来费点周折。
就是因为大家都想只用一个 ISP core 来同时处理两个以上的 sensor 采集到的图像信息,那多个sensor只能共享一个 isp core, 如何共享?
分时复用嘛,既然是分时复用就一定会出现 isp core在处理某个sensor采集到数据时其它sensor也采集完毕的场景,怎么办? 把其它sensor采集到数据丢掉?显然不合理,尤其在安防行业。那只能先把其它sensor采集到的帧数据缓存下来,待ISP core 处理完当前帧再去处理其它sensor才接到的帧数据, 要缓存这么多的数据,在isp core里加memory显然是不经济的,而且芯片面积也会大大增加。那怎么办?
只有系统memory中为这些暂时还不能得到ISP core帧数据申请空间缓存起来日后处理。好了有点跑题了,还是回到 mipi raw 数据的讨论吧。
下面放我们看看mipi raw究竟是怎么排列的。
2. MIPI RAW排列
先看raw8,因为raw8本来就一字节对齐的,所以没毛病
再看raw10, 5个byte存储4个像素,有一个byte是4个pixel共享的。
然后raw12, 3个byte存储2个pixel, 有一个byte是两个pixel共享的。
raw14, 7个byte存储4个pixel
raw16, raw16也是byte对其的,所以也没毛病,我们这里之提raw10 raw12 raw14这三种格式,网上也有一些文章介绍了 mipi raw如何转 raw ,但不够详细。
笔者前家公司的设计中考虑到了这一点,即在通过DMA写mipi raw 数据到DDR时做了这样的转换,软件同学就不用再自己想办法转了,所以之前没有特别注意过这个问题,现在不行了,必须要搞清楚它了。
以raw10举例
3. 转换code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char raw_array[3840*2160*2];
short pixel_array[3840*2160*2];
static const char *format_array[5] = {"RAW8", "RAW10", "RAW12", "RAW14", "RAW16"};
static const char *help = "help";
int main(int argc, char *argv[])
{
char *file_name = argv[1];
char *format = argv[2];
int width = atoi(argv[3]);
int height = atoi(argv[4]);
char out_file[256];
int format_index;
int byte_index = 0;
int pixel_index = 0;
int in_size = 0;
int out_size = 0;
printf("Usage: <filename> <format: RAW8/RAW10/RAW12/RAW14/RAW16> <width> <height>\r\n");
printf("file name: %s \r\n", file_name);
printf("format: %s \r\n", format);
printf("width: %d \r\n", width);
printf("height: %d \r\n", height);
FILE *raw_fb = fopen(file_name, "rb" );
if(!raw_fb)
{
printf("open input file faile \r\n");
return -1;
}
sprintf(out_file, "out_%s_%s", format, file_name);
printf("open input file name: %s\r\n", out_file);
FILE *pixel_fb = fopen(out_file, "wb");
if(!pixel_fb)
{
printf("open output file faile \r\n");
return -1;
}
for(int i=0; i<5; i++)
{
if(0 == strcmp(format_array[i], format))
{
format_index = i;
break;
}
format_index = 5;
}
printf("start convertion format_index: %d \r\n", format_index);
switch(format_index)
{
case 0:
in_size = width*height;
out_size = width*height;
break;
case 1:
in_size = width*height*10/8;
out_size = width*height*2;
break;
case 2:
in_size = width*height*12/8;
out_size = width*height*2;
break;
case 3:
in_size = width*height*14/8;
out_size = width*height*2;
break;
case 4:
in_size = width*height*2;
out_size = width*height*2;
break;
default:
printf("format is unsupport !!! \r\n");
break;
}
fread(raw_array, 1, in_size, raw_fb);
switch(format_index)
{
case 0:
// RAW8 don't need convert
break;
case 1:
// RAW10
for(byte_index=0, pixel_index=0; byte_index < (in_size-5); )
{
pixel_array[pixel_index+0] = (((short)(raw_array[byte_index+0]))<<2) & 0x03FC;
pixel_array[pixel_index+0] = pixel_array[pixel_index+0] | (short)((raw_array[byte_index+4]>>0) & 0x0003);
pixel_array[pixel_index+1] = (((short)(raw_array[byte_index+1]))<<2) & 0x03FC;
pixel_array[pixel_index+1] = pixel_array[pixel_index+1] | (short)((raw_array[byte_index+4]>>2) & 0x0003);
pixel_array[pixel_index+2] = (((short)(raw_array[byte_index+2]))<<2) & 0x03FC;
pixel_array[pixel_index+2] = pixel_array[pixel_index+2] | (short)((raw_array[byte_index+4]>>4) & 0x0003);
pixel_array[pixel_index+3] = (((short)(raw_array[byte_index+3]))<<2) & 0x03FC;
pixel_array[pixel_index+3] = pixel_array[pixel_index+3] | (short)((raw_array[byte_index+4]>>6) & 0x0003);
byte_index = byte_index + 5;
pixel_index = pixel_index + 4;
}
break;
case 2:
// RAW12
for(byte_index=0, pixel_index=0; byte_index < (in_size-3); )
{
pixel_array[pixel_index+0] = (((short)(raw_array[byte_index+0]))<<4) & 0x0FF0;
pixel_array[pixel_index+0] = pixel_array[pixel_index+0] | (short)((raw_array[byte_index+2]>>0) & 0x000F);
pixel_array[pixel_index+1] = (((short)(raw_array[byte_index+1]))<<4) & 0x0FF0;
pixel_array[pixel_index+1] = pixel_array[pixel_index+1] | (short)((raw_array[byte_index+2]>>4) & 0x000F);
byte_index = byte_index + 3;
pixel_index = pixel_index + 2;
}
break;
case 3:
//RAW14
for(byte_index=0, pixel_index=0; byte_index < (in_size-7); )
{
pixel_array[pixel_index+0] = (((short)(raw_array[byte_index+0]))<<6) & 0x3FC0;
pixel_array[pixel_index+0] = pixel_array[pixel_index+0] | (short)((raw_array[byte_index+4]>>0) & 0x003F);
pixel_array[pixel_index+1] = (((short)(raw_array[byte_index+1]))<<6) & 0x3FC0;
pixel_array[pixel_index+1] = pixel_array[pixel_index+1] | (short)((raw_array[byte_index+4]>>6) & 0x0003);
pixel_array[pixel_index+1] = pixel_array[pixel_index+1] | (short)((raw_array[byte_index+5]>>0) & 0x000F);
pixel_array[pixel_index+2] = (((short)(raw_array[byte_index+2]))<<6) & 0x3FC0;
pixel_array[pixel_index+2] = pixel_array[pixel_index+2] | (short)((raw_array[byte_index+5]>>4) & 0x000F);
pixel_array[pixel_index+2] = pixel_array[pixel_index+2] | (short)((raw_array[byte_index+6]>>0) & 0x0003);
pixel_array[pixel_index+3] = (((short)(raw_array[byte_index+3]))<<6) & 0x3FC0;
pixel_array[pixel_index+3] = pixel_array[pixel_index+3] | (short)((raw_array[byte_index+6]>>2) & 0x003F);
byte_index = byte_index + 7;
pixel_index = pixel_index + 4;
}
break;
case 4:
// RAW16 don't need convert
break;
default:
printf("formt is unsupport !!! \r\n");
break;
}
fwrite(pixel_array, 1, out_size, pixel_fb);
fclose(raw_fb);
fclose(pixel_fb);
printf("convert finished !!! \r\n");
return 0;
}