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那段代码了。
这个是可以用的,而且用效率最低的办法去做,也就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; }