dm365的resizer使用
在用dm365的时候,用resizer的ioctl,一直不好使,后来在ti论坛上看到一个人的讲解,原来是bootargs的错。在配置的时候,有一项dm365_imp.oper_mode=1,这个要配成1.
下面是我的配置,仅供参考
setenv bootargs mem=64M console=ttyS0,115200n8 noinitrd rw ip=192.168.0.7:192.168.0.1:255.255.255.0 nfsroot=192.168.0.8:/home/mick/davinci/nfs_filesystem/dm365_filesys davinci_enc_mngr.ch0_output=LCD video=davincifb:vid0=720x480x16,2025K@0,0:osd0=720x480x16,1350K@0,0 davinci_capture.device_type=4 dm365_imp.oper_mode=1
dm365的LCD显示
对DM365的decode做了修改,想让他原来的从小电视输出,改成用LCD输出。在DM365上面接了一个LCD屏幕。屏幕是800*480,被设置成720*480大小。从decode出来的数据,应该是YUV420PSEMI的,而就目前我知道的,LCD输出时UYVY的422格式。声明一下,目前没太多文档读,有些地方可能不对,希望谁发现了,就回帖告诉我一声,不胜感激。
decode是用fifo活的的一帧的数据,在一个Buffer_Handle中。声明了两个hSrcBuf, hDstBuf,分别是源和目的。
下面是两行打印信息,关于这两个Buffer_Handle的。
************hSrc below:
[15] @ 0x4378a000 (0x86ee2000 phys) numBytes 718848 (718848) useMask 2 (3) ref no
Width 720 (720) Height 480 (576) Pos 24x24 LineLength 768 (720)
************hDst below:
[0] @ 0x40c00000 (0x80a00000 phys) numBytes 691200 (691200) useMask 0 (1) ref yes
Width 720 (720) Height 480 (480) Pos 0x0 LineLength 1440 (1440)
这两个视频帧的物理空间上的值在括号里面,是虚拟出来的空间的值在括号前面。可以看到,源的linelength是768,所以拷贝的时候,后面会有一些无用的数据。没有用decode自带的那个framecopy什么的,因为我用那个图像只能被扁着显示在左边的一半地方……然后我调用了ccv里面的420到422的转化,然后手动修改了dmai里面的转化代码,目前得到了黑白的数据,也就是y值。但是u,v的值还没搞好,现在是黑白图像,不过能够全屏720*480显示了。
for(i = 0; i < srcDim.height; i++) {
for(j=0; j < srcDim.width/4; j++) {
*dst++ = *src_u;
*dst++ = *src++;
*dst++ = *src_v;
*dst++ = *src++;
*dst++ = *src_u;
*dst++ = *src++;
*dst++ = *src_v;
*dst++ = *src++;
src_u += 2;
src_v += 2;
}
dst = dst + (dstDim.lineLength - srcDim.width*2);
src = src + (srcDim.lineLength - srcDim.width);
src_u = src_u + (srcDim.lineLength - srcDim.width);
src_v = src_v + (srcDim.lineLength - srcDim.width);
}
这是我幻想的,算上u跟v的转化,可是u跟v的效果不行,颜色没加上……继续努力中
不过,看dmai的代码,好像dm365不支持硬件ccv转化,用这种软的,相当浪费arm资源,打印的arm显示,已经占用超过90%了,而且只能显示5帧左右。
之前能显示了,后来仔细查了一下内核代码,发现可以不用去掉那个check var了。之前报错的原因是,在davincifb.c的convert_osd_to_fb_var函数中,case PIXFMT_NV12中少了一个break,所以出现var的像素值一直会变成32.所以,在这里加一个break,就不用注释掉check var那段代码了。
dm365 动态切换采集编码分辨率
这个是可以用的,而且用效率最低的办法去做,也就1.5秒左右的切换时间。这种来回变换的切换数据流可以按分辨率保存成不同文件,也可以通过网络发出去。VLC使用1.2的版本就能够动态切换分辨率了。以前经常使用0.8.6的版本,觉得挺好用,但是切屏这个就不行了,必须要换高版本。
DaVinci的Buffer_Handle和BufTab Cmem函数调用
aVinci的dvsdk里面,所有的内存用的都是CMEM,而比较上层的一个封装就是BufTab和Buffer_Handle了
每个Tab可以控制好多块内存块。具体到内存块有两种,一种是创建的时候指定他的大小啊,物理地址啥的。另外一种就是仅仅创建出这个结构的一个实例,而物理地址啊啥的都留空,等到回头用的时候,用指针搞定。
第一类,对应的配置里面有一个叫reference的变量,配成false的话,创建的时候就直接创建出来内存块了,reference这点BufTab和Buffer_Handle的创建配置是一样的。
第二类,reference配置成true,这样的话,创建之后,指针没有指向,而需要后面重新指定。指定的时候,要用Buffer_setUserPtr,同时还要设一下大小,Buffer_setNumBytesUsed,同时用这两个,不然程序会down掉的。
我试验了,使用CMEM手动分配物理空间,用reference=TRUE的配置,声明一个Buffer_handle的结构,使用cmem函数直接申请空间,然后再配置Buffer_handle的指针。
CMEM_AllocParams cmem_params;
Int8 *ptr_area_fifo;
cmem_params.type = CMEM_POOL;
cmem_params.flags = CMEM_NONCACHED;
for(loop_num = 0; loop_num < fifo_total; loop_num++) {
ptr_area_fifo = (Int8 *)CMEM_alloc(bufSize, &cmem_params);
//hBufTab is created while its reference=TRUE.
hDstBuf = BufTab_getBuf(hBufTab, loop_num);
Buffer_setNumBytesUsed(hDstBuf, bufSize);
if (Buffer_setUserPtr(hDstBuf, ptr_area_fifo) < 0) {
printf("error while set prt into bufTab, id=%d/n", loop_num);
}
}
/******************************************************************************
* Resize_create
******************************************************************************/
Resize_Handle Resize_create(Resize_Attrs *attrs)
{
#ifdef CONFIG_DM365_IPIPE
Resize_Handle hResize;
unsigned long oper_mode;
assert(attrs);
hResize = (Resize_Handle)calloc(1, sizeof(Resize_Object));
if (hResize == NULL) {
Dmai_err0("Failed to allocate space for Framecopy Object\n");
return NULL;
}
/* Open resizer device */
hResize->fd = open(RESIZER_DEVICE, O_RDWR);
if (hResize->fd == -1) {
Dmai_err1("Failed to open %s\n", RESIZER_DEVICE);
return NULL;
}
oper_mode = IMP_MODE_SINGLE_SHOT;
if (ioctl(hResize->fd,RSZ_S_OPER_MODE, &oper_mode) < 0) {
Dmai_err0("Resizer can't set operation mode\n");
goto cleanup;
}
if (ioctl(hResize->fd,RSZ_G_OPER_MODE, &oper_mode) < 0) {
Dmai_err0("Resizer can't get operation mode\n");
goto cleanup;
}
if (oper_mode != IMP_MODE_SINGLE_SHOT) {
Dmai_err1("Resizer can't set operation mode single shot, the mode is %d\n",
oper_mode);
goto cleanup;
}
return hResize;
cleanup:
close(hResize->fd);
hResize->fd = 0;
return NULL;
#else
Dmai_err0("not implemented\n");
return NULL;
#endif
}
/******************************************************************************
* Resize_config
******************************************************************************/
Int Resize_config(Resize_Handle hResize,
Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf)
{
#ifdef CONFIG_DM365_IPIPE
BufferGfx_Dimensions srcDim, dstDim;
UInt hDif;
UInt vDif;
struct rsz_channel_config rsz_chan_config;
struct rsz_single_shot_config rsz_ss_config;
/* Make sure our input parameters are valid */
if (!hResize) {
Dmai_err0("Resize_Handle parameter must not be NULL\n");
return Dmai_EINVAL;
}
if (!hSrcBuf) {
Dmai_err0("Source buffer parameter must not be NULL\n");
return Dmai_EINVAL;
}
if (!hDstBuf) {
Dmai_err0("Destination buffer parameter must not be NULL\n");
return Dmai_EINVAL;
}
/* Buffer needs to be graphics buffers */
if (Buffer_getType(hSrcBuf) != Buffer_Type_GRAPHICS ||
Buffer_getType(hDstBuf) != Buffer_Type_GRAPHICS) {
Dmai_err0("Src and dst buffers need to be graphics buffers\n");
return Dmai_EINVAL;
}
BufferGfx_getDimensions(hSrcBuf, &srcDim);
BufferGfx_getDimensions(hDstBuf, &dstDim);
if (dstDim.width <= 0) {
Dmai_err0("Destination buffer width must be greater than zero\n");
return Dmai_EINVAL;
}
if (dstDim.height <= 0) {
Dmai_err0("Destination buffer height must be greater than zero\n");
return Dmai_EINVAL;
}
if ((srcDim.lineLength & 0x1F) != 0) {
Dmai_err0("Source buffer pitch must be a multiple of 32 bytes\n");
return Dmai_EINVAL;
}
if ((dstDim.lineLength & 0x1F) != 0) {
Dmai_err0("Destination buffer pitch must be a multiple of 32 bytes\n");
return Dmai_EINVAL;
}
/* Check for valid buffer scaling */
hDif = srcDim.width * 256 / dstDim.width;
vDif = srcDim.height * 256 / dstDim.height;
if (hDif < 32) {
Dmai_err0("Horizontal up-scaling must not exceed 8x\n");
return Dmai_EINVAL;
}
if (hDif > 4096) {
Dmai_err0("Horizontal down-scaling must not exceed 1/16x\n");
return Dmai_EINVAL;
}
if (vDif < 32) {
Dmai_err0("Vertical up-scaling must not exceed 8x\n");
return Dmai_EINVAL;
}
if (vDif > 4096) {
Dmai_err0("Vertical down-scaling must not exceed 1/16x\n");
return Dmai_EINVAL;
}
/* Set the driver default parameters and retrieve what was set */
Dmai_clear(rsz_ss_config);
rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT;
rsz_chan_config.chain = 0;
rsz_chan_config.len = 0;
rsz_chan_config.config = NULL; /* to set defaults in driver */
if (ioctl(hResize->fd, RSZ_S_CONFIG, &rsz_chan_config) < 0) {
Dmai_err0("Error in setting default configuration for single shot mode\n");
goto cleanup;
}
/* default configuration setting in Resizer successfull */
Dmai_clear(rsz_ss_config);
rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT;
rsz_chan_config.chain = 0;
rsz_chan_config.len = sizeof(struct rsz_single_shot_config);
rsz_chan_config.config = &rsz_ss_config;
if (ioctl(hResize->fd, RSZ_G_CONFIG, &rsz_chan_config) < 0) {
Dmai_err0("Error in getting resizer channel configuration from driver\n");
goto cleanup;
}
/* input params are set at the resizer */
rsz_ss_config.input.image_width = srcDim.width;
rsz_ss_config.input.image_height = srcDim.height;
rsz_ss_config.input.ppln = rsz_ss_config.input.image_width + 8;
rsz_ss_config.input.lpfr = rsz_ss_config.input.image_height + 10;
rsz_ss_config.input.pix_fmt = pixFormatConversion(BufferGfx_getColorSpace(hSrcBuf));
rsz_ss_config.output1.pix_fmt = pixFormatConversion(BufferGfx_getColorSpace(hDstBuf));
rsz_ss_config.output1.enable = 1;
rsz_ss_config.output1.width = dstDim.width;
rsz_ss_config.output1.height = dstDim.height;
rsz_ss_config.output2.enable = 0;
rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT;
rsz_chan_config.chain = 0;
rsz_chan_config.len = sizeof(struct rsz_single_shot_config);
if (ioctl(hResize->fd, RSZ_S_CONFIG, &rsz_chan_config) < 0) {
Dmai_err0("Error in setting default configuration for single shot mode\n");
goto cleanup;
}
rsz_chan_config.oper_mode = IMP_MODE_SINGLE_SHOT;
rsz_chan_config.chain = 0;
rsz_chan_config.len = sizeof(struct rsz_single_shot_config);
/* read again and verify */
if (ioctl(hResize->fd, RSZ_G_CONFIG, &rsz_chan_config) < 0) {
Dmai_err0("Error in getting configuration from driver\n");
goto cleanup;
}
return Dmai_EOK;
cleanup:
close(hResize->fd);
hResize->fd = 0;
return Dmai_EFAIL;
#else
Dmai_err0("not implemented\n");
return Dmai_ENOTIMPL;
#endif
}
/******************************************************************************
* Resize_execute
******************************************************************************/
Int Resize_execute(Resize_Handle hResize,
Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf)
{
#ifdef CONFIG_DM365_IPIPE
struct imp_convert rsz;
BufferGfx_Dimensions srcDim;
BufferGfx_Dimensions dstDim;
UInt32 srcOffset;
UInt32 dstOffset;
assert(hResize);
assert(hSrcBuf);
assert(hDstBuf);
Dmai_clear(rsz);
BufferGfx_getDimensions(hSrcBuf, &srcDim);
BufferGfx_getDimensions(hDstBuf, &dstDim);
srcOffset = srcDim.y * srcDim.lineLength + (srcDim.x << 1);
dstOffset = dstDim.y * dstDim.lineLength + (dstDim.x << 1);
rsz.in_buff.index = -1;
rsz.in_buff.buf_type = IMP_BUF_IN;
rsz.in_buff.offset = (UInt32) Buffer_getUserPtr(hSrcBuf) + srcOffset;
rsz.in_buff.size = Buffer_getSize(hSrcBuf);
rsz.out_buff1.index = -1;
rsz.out_buff1.buf_type = IMP_BUF_OUT1;
rsz.out_buff1.offset = (UInt32) Buffer_getUserPtr(hDstBuf) + dstOffset;
rsz.out_buff1.size = Buffer_getSize(hDstBuf);
/*
* The IPIPE requires that the memory offsets of the input and output
* buffers start on 32-byte boundaries.
*/
assert((rsz.in_buff.offset & 0x1F) == 0);
assert((rsz.out_buff1.offset & 0x1F) == 0);
/* Start IPIPE operation */
if (ioctl(hResize->fd, RSZ_RESIZE, &rsz) == -1) {
Dmai_err0("Failed RSZ_RESIZE\n");
return Dmai_EFAIL;
}
Buffer_setNumBytesUsed(hDstBuf, Buffer_getNumBytesUsed(hSrcBuf));
return Dmai_EOK;
#else
Dmai_err0("not implemented\n");
return Dmai_ENOTIMPL;
#endif
}
/******************************************************************************
* Resize_delete
******************************************************************************/
Int Resize_delete(Resize_Handle hResize)
{
#ifdef CONFIG_DM365_IPIPE
if (hResize) {
close(hResize->fd);
free(hResize);
}
#endif
return Dmai_EOK;
}
/******************************************************************************
* Initialize & configure resizer in on-the-fly (continous) mode
******************************************************************************/
Int Resizer_continuous_config(void)
{
#ifdef CONFIG_DM365_IPIPE
Int rsz_fd;
unsigned int oper_mode, user_mode;
struct rsz_channel_config rsz_chan_config;
struct rsz_continuous_config rsz_cont_config;
user_mode = IMP_MODE_CONTINUOUS;
rsz_fd = open((const char *)RESIZER_DEVICE, O_RDWR);
if(rsz_fd <= 0) {
Dmai_err0("Cannot open resize device \n");
return NULL;
}
if (ioctl(rsz_fd, RSZ_S_OPER_MODE, &user_mode) < 0) {
Dmai_err1("Can't set operation mode (%s)\n", strerror(errno));
close(rsz_fd);
return Dmai_EFAIL;
}
if (ioctl(rsz_fd, RSZ_G_OPER_MODE, &oper_mode) < 0) {
Dmai_err1("Can't get operation mode (%s)\n", strerror(errno));
close(rsz_fd);
return Dmai_EFAIL;
}
if (oper_mode == user_mode) {
Dmai_dbg0("Successfully set mode to continuous in resizer\n");
} else {
Dmai_err0("Failed to set mode to continuous in resizer\n");
close(rsz_fd);
return Dmai_EFAIL;
}
/* set configuration to chain resizer with preview */
rsz_chan_config.oper_mode = user_mode;
rsz_chan_config.chain = 1;
rsz_chan_config.len = 0;
rsz_chan_config.config = NULL; /* to set defaults in driver */
if (ioctl(rsz_fd, RSZ_S_CONFIG, &rsz_chan_config) < 0) {
Dmai_err1("Error in setting default configuration in resizer (%s)\n",
strerror(errno));
close(rsz_fd);
return Dmai_EFAIL;
}
bzero(&rsz_cont_config, sizeof(struct rsz_continuous_config));
rsz_chan_config.oper_mode = user_mode;
rsz_chan_config.chain = 1;
rsz_chan_config.len = sizeof(struct rsz_continuous_config);
rsz_chan_config.config = &rsz_cont_config;
if (ioctl(rsz_fd, RSZ_G_CONFIG, &rsz_chan_config) < 0) {
Dmai_err1("Error in getting channel configuration from resizer (%s)\n",
strerror(errno));
close(rsz_fd);
return Dmai_EFAIL;
}
/* we can ignore the input spec since we are chaining. So only
set output specs */
rsz_cont_config.output1.enable = 1;
rsz_cont_config.output2.enable = 0;
rsz_chan_config.len = sizeof(struct rsz_continuous_config);
rsz_chan_config.config = &rsz_cont_config;
if (ioctl(rsz_fd, RSZ_S_CONFIG, &rsz_chan_config) < 0) {
Dmai_err1("Error in setting resizer configuration (%s)\n",
strerror(errno));
close(rsz_fd);
return Dmai_EFAIL;
}
Dmai_dbg0("Resizer initialized\n");
return rsz_fd;
#else
Dmai_err0("not implemented\n");
return Dmai_ENOTIMPL;
#endif
}
/******************************************************************************
* Initialize & configure previewer in on-the-fly (continous) mode
******************************************************************************/
Int Previewer_continuous_config(Bool setRgbColorPallet)
{
#ifdef CONFIG_DM365_IPIPE
Int preview_fd;
unsigned int oper_mode, user_mode;
struct prev_channel_config prev_chan_config;
struct prev_continuous_config prev_cont_config;
struct prev_cap cap;
struct prev_module_param mod_param;
user_mode = IMP_MODE_CONTINUOUS;
preview_fd = open((const char *)PREVIEWER_DEVICE, O_RDWR);
if(preview_fd <= 0) {
Dmai_err0("Cannot open previewer device \n");
return NULL;
}
if (ioctl(preview_fd,PREV_S_OPER_MODE, &user_mode) < 0) {
Dmai_err1("Can't set operation mode in previewer (%s)\n", strerror(errno));
close(preview_fd);
return Dmai_EFAIL;
}
if (ioctl(preview_fd,PREV_G_OPER_MODE, &oper_mode) < 0) {
Dmai_err1("Can't get operation mode from previewer (%s)\n", strerror(errno));
close(preview_fd);
return Dmai_EFAIL;
}
if (oper_mode == user_mode) {
Dmai_dbg0("Operating mode changed successfully to continuous in previewer\n");
} else {
Dmai_err0("failed to set mode to continuous in previewer\n");
close(preview_fd);
return Dmai_EFAIL;
}
prev_chan_config.oper_mode = oper_mode;
prev_chan_config.len = 0;
prev_chan_config.config = NULL; /* to set defaults in driver */
if (ioctl(preview_fd, PREV_S_CONFIG, &prev_chan_config) < 0) {
Dmai_err1("Error in setting default previewer configuration (%s)\n",
strerror(errno));
close(preview_fd);
return Dmai_EFAIL;
}
if (setRgbColorPallet) {
Dmai_dbg0("Setting RGB color pallet\n");
prev_chan_config.oper_mode = oper_mode;
prev_chan_config.len = sizeof(struct prev_continuous_config);
prev_chan_config.config = &prev_cont_config; /* to set defaults in driver */
if (ioctl(preview_fd, PREV_G_CONFIG, &prev_chan_config) < 0) {
Dmai_err1("Error in setting default previewer configuration (%s)\n",
strerror(errno));
close(preview_fd);
return Dmai_EFAIL;
}
prev_chan_config.oper_mode = oper_mode;
prev_chan_config.len = sizeof(struct prev_continuous_config);
prev_chan_config.config = &prev_cont_config; /* to set defaults in driver */
prev_cont_config.input.colp_elep= IPIPE_BLUE;
prev_cont_config.input.colp_elop= IPIPE_GREEN_BLUE;
prev_cont_config.input.colp_olep= IPIPE_GREEN_RED;
prev_cont_config.input.colp_olop= IPIPE_RED;
if (ioctl(preview_fd, PREV_S_CONFIG, &prev_chan_config) < 0) {
Dmai_err1("Error in setting default previewer configuration (%s)\n",
strerror(errno));
close(preview_fd);
return Dmai_EFAIL;
}
cap.index=0;
while (1) {
if (ioctl(preview_fd , PREV_ENUM_CAP, &cap) < 0) {
break;
}
strcpy(mod_param.version,cap.version);
mod_param.module_id = cap.module_id;
// using defaults
Dmai_dbg1("Setting default for %s\n", cap.module_name);
mod_param.param = NULL;
if (ioctl(preview_fd, PREV_S_PARAM, &mod_param) < 0) {
Dmai_err1("Error in Setting %s params from driver\n", cap.module_name);
close(preview_fd);
return Dmai_EFAIL;
}
cap.index++;
}
}
Dmai_dbg0("Previewer initialized\n");
return preview_fd;
#else
Dmai_err0("not implemented\n");
return Dmai_ENOTIMPL;
#endif
}
/******************************************************************************
* Resizer_continuous_delete
******************************************************************************/
Int Resizer_continuous_delete(Int fd)
{
if (fd) {
if (close(fd) == -1) {
Dmai_err1("Failed to close resizer device (%s)\n", strerror(errno));
return Dmai_EIO;
}
}
return Dmai_EOK;
}
/******************************************************************************
* Previewer_continuous_delete
******************************************************************************/
Int Previewer_continuous_delete(Int fd)
{
if (fd) {
if (close(fd) == -1) {
Dmai_err1("Failed to close previewer device (%s)\n", strerror(errno));
return Dmai_EIO;
}
}
return Dmai_EOK;
}