Пример #1
0
int VpuDec::set_DecOpenParam()
{
	int ret = -1;
	memset(&handle,0,sizeof(DecHandle));
	DecOpenParam oparam;// = {0};
	memset(&oparam, 0, sizeof(DecOpenParam)); //must to clean to 0
	
	allocHwBuffer(Dec_RingBuf_Size);
	
	oparam.bitstreamFormat = (CodStd)dec_format;
	oparam.bitstreamBuffer = Dec_bufZone.pStartAddr;
	oparam.bitstreamBufferSize = Dec_bufZone.bufSize;
	oparam.pBitStream = (Uint8 *)Dec_bufZone.vStartaddr;
	oparam.reorderEnable = 1;
	oparam.mp4DeblkEnable = 0;
	oparam.chromaInterleave = 0;
	oparam.mp4Class = 0;
	if (cpu_is_mx6x())
		oparam.avcExtension = 0;
	oparam.mjpg_thumbNailDecEnable = 0;
	oparam.mapType = 0;
	oparam.tiled2LinearEnable = 0;
	oparam.bitstreamMode = 1;
	oparam.jpgLineBufferMode = 1;
	
	if (dec_format == STD_AVC) {
		ps_mem_desc.size = PS_SAVE_SIZE;
		ret = IOGetPhyMem(&ps_mem_desc);
		if (ret){
			printf("Unable to obtain physical ps save mem,LINE%d\n",__LINE__);
			return -1;
		}
		
		oparam.psSaveBuffer = ps_mem_desc.phy_addr;
		oparam.psSaveBufferSize = PS_SAVE_SIZE;
	}
		//printf("bitstreamFormat %x, bitstreamBuffer %x,bitstreamBufferSize %d, pBitStream %x\n",oparam.bitstreamFormat,
			//oparam.bitstreamBuffer,oparam.bitstreamBufferSize,oparam.pBitStream);

	ret = vpu_DecOpen(&handle, &oparam);
	if (ret != RETCODE_SUCCESS) {
		printf("vpu_DecOpen failed, ret:%d\n", ret);
		return -1;
	}
	
	return 0;
}
int
parse_args(int argc, char *argv[], int i)
{
	int status = 0, opt, val;

	input_arg[i].cmd.chromaInterleave = 1;
	if (cpu_is_mx6x())
		input_arg[i].cmd.bs_mode = 1;

	do {
		opt = getopt(argc, argv, options);
		switch (opt)
		{
		case 'i':
			strncpy(input_arg[i].cmd.input, optarg, MAX_PATH);
			input_arg[i].cmd.src_scheme = PATH_FILE;
			break;
		case 'o':
			if (input_arg[i].cmd.dst_scheme == PATH_NET) {
				warn_msg("-o ignored because of -n\n");
				break;
			}
			strncpy(input_arg[i].cmd.output, optarg, MAX_PATH);
			input_arg[i].cmd.dst_scheme = PATH_FILE;
			break;
		case 'x':
			val = atoi(optarg);
			if ((input_arg[i].mode == ENCODE) || (input_arg[i].mode == LOOPBACK))
				input_arg[i].cmd.video_node_capture = val;
			else {
				if (val == 1) {
					input_arg[i].cmd.dst_scheme = PATH_IPU;
					info_msg("Display through IPU LIB\n");
					if (cpu_is_mx6x())
						warn_msg("IPU lib is OBSOLETE, please try other renderer\n");
#ifdef BUILD_FOR_ANDROID
				} else if (val == 2) {
					input_arg[i].cmd.dst_scheme = PATH_G2D;
					info_msg("Display through G2D\n");
#endif
				} else {
					input_arg[i].cmd.dst_scheme = PATH_V4L2;
					info_msg("Display through V4L2\n");
					input_arg[i].cmd.video_node = val;
				}
				if (cpu_is_mx27() &&
					(input_arg[i].cmd.dst_scheme == PATH_IPU)) {
					input_arg[i].cmd.dst_scheme = PATH_V4L2;
					warn_msg("ipu lib disp only support in ipuv3\n");
				}
			}
			break;
		case 'n':
			if (input_arg[i].mode == ENCODE) {
				/* contains the ip address */
				strncpy(input_arg[i].cmd.output, optarg, 64);
				input_arg[i].cmd.dst_scheme = PATH_NET;
			} else {
				warn_msg("-n option used only for encode\n");
			}
			break;
		case 'p':
			input_arg[i].cmd.port = atoi(optarg);
			break;
		case 'r':
			input_arg[i].cmd.rot_angle = atoi(optarg);
			if (input_arg[i].cmd.rot_angle)
				input_arg[i].cmd.rot_en = 1;
			break;
		case 'u':
			input_arg[i].cmd.ext_rot_en = atoi(optarg);
			/* ipu/gpu rotation will override vpu rotation */
			if (input_arg[i].cmd.ext_rot_en)
				input_arg[i].cmd.rot_en = 0;
			break;
		case 'f':
			input_arg[i].cmd.format = atoi(optarg);
			break;
		case 'c':
			input_arg[i].cmd.count = atoi(optarg);
			break;
		case 'v':
			input_arg[i].cmd.vdi_motion = optarg[0];
			break;
		case 'w':
			input_arg[i].cmd.width = atoi(optarg);
			break;
		case 'h':
			input_arg[i].cmd.height = atoi(optarg);
			break;
		case 'j':
			input_arg[i].cmd.loff = atoi(optarg);
			break;
		case 'k':
			input_arg[i].cmd.toff = atoi(optarg);
			break;
		case 'g':
			input_arg[i].cmd.gop = atoi(optarg);
			break;
		case 's':
			if (cpu_is_mx6x())
				input_arg[i].cmd.bs_mode = atoi(optarg);
			else
				input_arg[i].cmd.prescan = atoi(optarg);
			break;
		case 'b':
			input_arg[i].cmd.bitrate = atoi(optarg);
			break;
		case 'd':
			input_arg[i].cmd.deblock_en = atoi(optarg);
			break;
		case 'e':
			input_arg[i].cmd.dering_en = atoi(optarg);
			break;
		case 'm':
			input_arg[i].cmd.mirror = atoi(optarg);
			if (input_arg[i].cmd.mirror)
				input_arg[i].cmd.rot_en = 1;
			break;
		case 't':
			input_arg[i].cmd.chromaInterleave = atoi(optarg);
			break;
		case 'l':
			input_arg[i].cmd.mp4_h264Class = atoi(optarg);
			break;
		case 'a':
			input_arg[i].cmd.fps = atoi(optarg);
			break;
		case 'y':
			input_arg[i].cmd.mapType = atoi(optarg);
			break;
		case 'q':
			input_arg[i].cmd.quantParam = atoi(optarg);
			break;
		case -1:
			break;
		default:
			status = -1;
			break;
		}
	} while ((opt != -1) && (status == 0));

	optind = 1;
	return status;
}
Пример #3
0
int VpuDec::decode(VencBlk * src, ImgBlk * dest)//blocking
{	
	int ret = 1; 
	int loop_id = 0;
	int imageSize;
	DecOutputInfo outinfo = {0};
	DecParam decparam = {0};

	if(dec_fb == NULL || dec_pfbpool == NULL){
		if (write_Src_Ringbuf(src) == -1 || get_DecInitialInfo(src) == -1 || calloc_FrameBuff(src) == -1){
			printf("Config VPU error:VencBlk codec 0x%x, %dx%d, frameSize %d, frameType %d\n",src->codec,src->width,src->height,src->frameSize,src->frameType);			
			return -1;
		}
		decparam.dispReorderBuf = 0;
		decparam.skipframeMode = 0;
		decparam.skipframeNum = 0;
		decparam.iframeSearchEnable = 0;

		if(dec_format == STD_MJPG)
			vpu_DecGiveCommand(handle, SET_ROTATOR_STRIDE, &src->width);
		
	}else{
		ret = write_Src_Ringbuf(src);
			if (ret < 0) {
				printf("read data failed\n");
				return -1;
			}

	}
	if(dec_format == STD_MJPG){
			decparam.chunkSize = src->frameSize;
			decparam.phyJpgChunkBase = Dec_bufZone.pStartAddr;
			decparam.virtJpgChunkBase = (unsigned char*)Dec_bufZone.vStartaddr;
			vpu_DecGiveCommand(handle, SET_ROTATOR_OUTPUT,(void *)&dec_fb[0]);
	}

	imageSize = src->width * src->height * 3 / 2;
	
	ret = vpu_DecStartOneFrame(handle, &decparam);
	if (ret != RETCODE_SUCCESS) {
			printf("DecStartOneFrame failed, ret=%d,LINE:%d\n", ret,__LINE__);
			return -1;
	}

			loop_id = 0;

	while (vpu_IsBusy()) {
			
			if (loop_id == 50) {
				ret = vpu_SWReset(handle, 0);
				return -1;
			}

			vpu_WaitForInt(100);
			loop_id ++;
	}

	ret = vpu_DecGetOutputInfo(handle, &outinfo);
	if (ret != RETCODE_SUCCESS) {
			printf("vpu_DecGetOutputInfo failed Err code is %d\n"
				"\tframe_id = %d\n", ret, (int)frame_id);
			return -1;
		}
	
	if (cpu_is_mx6x() && (outinfo.decodingSuccess & 0x10)) {
			printf("vpu needs more bitstream in rollback mode\n"
				"\tframe_id = %d\n", (int)frame_id);

			return -1;
	}

	if (outinfo.notSufficientPsBuffer) {
		printf("PS Buffer overflow,LINE:%d\n",__LINE__);
		return -1;
	}

	if (outinfo.notSufficientSliceBuffer) {
		printf("Slice Buffer overflow,LINE:%d\n",__LINE__);
		return -1;
	}

	if (outinfo.indexFrameDisplay == -1){
			printf("VPU has no more display data,LINE:%d\n",__LINE__);
			return -1;
	}

	if ((outinfo.indexFrameDisplay == -3) ||(outinfo.indexFrameDisplay == -2)) {
		printf("VPU doesn't have picture to be displayed.\n"
				"\toutinfo.indexFrameDisplay = %d\n",
					outinfo.indexFrameDisplay);

			if (disp_clr_index >= 0) {
				ret = vpu_DecClrDispFlag(handle, disp_clr_index);
				if (ret)
					printf("vpu_DecClrDispFlag failed Error code"
								" %d\n", ret);
			}
			disp_clr_index = outinfo.indexFrameDisplay;		
		}
		
	dis_index = outinfo.indexFrameDisplay;
	dest->vaddr = (void *)(dec_pfbpool[dis_index]->addrY + (dec_pfbpool[dis_index]->desc.virt_uaddr- dec_pfbpool[dis_index]->desc.phy_addr)); 
	dest->paddr = dec_pfbpool[dis_index]->desc.phy_addr; //physical address
	dest->size = imageSize;
	dest->height = src->height;
	dest->width = src->width;
	dest->fourcc = PIX_FMT_YUV420P;//src->codec;
	dest->pts = src->pts;

	//printf("dis_index:%d,frame_id:%d,disp_clr_index:%d\n",dis_index,frame_id,disp_clr_index);

	if(dec_format == STD_AVC){
		if (disp_clr_index >= 0) {
			ret = vpu_DecClrDispFlag(handle,disp_clr_index);
			if (ret)
				printf("vpu_DecClrDispFlag failed Error code%d,LINE:%d\n", ret,__LINE__);
		}
	}
	
	disp_clr_index = outinfo.indexFrameDisplay;
	frame_id++;
	return 1;

}
Пример #4
0
struct vpu_display *
v4l_display_open(struct decode *dec, int nframes, struct rot rotation, Rect cropRect)
{
	int width = dec->picwidth;
	int height = dec->picheight;
	int left = cropRect.left;
	int top = cropRect.top;
	int right = cropRect.right;
	int bottom = cropRect.bottom;
	int disp_width = dec->cmdl->width;
	int disp_height = dec->cmdl->height;
	int disp_left =  dec->cmdl->loff;
	int disp_top =  dec->cmdl->toff;
	int fd = -1, err = 0, out = 0, i = 0;
	char v4l_device[80], node[8];
	struct v4l2_cropcap cropcap = {0};
	struct v4l2_crop crop = {0};
	struct v4l2_framebuffer fb = {0};
	struct v4l2_format fmt = {0};
	struct v4l2_requestbuffers reqbuf = {0};
	struct v4l2_mxc_offset off = {0};
	struct v4l2_rect icrop = {0};
	struct vpu_display *disp;
	int fd_fb;
	char *tv_mode, *test_mode;
	char motion_mode = dec->cmdl->vdi_motion;
	struct mxcfb_gbl_alpha alpha;

	int ratio = 1;

	if (cpu_is_mx27()) {
		out = 0;
	} else {
		out = 3;
#ifdef BUILD_FOR_ANDROID
		fd_fb = open("/dev/graphics/fb0", O_RDWR, 0);
#else
		fd_fb = open("/dev/fb0", O_RDWR, 0);
#endif
		if (fd_fb < 0) {
			err_msg("unable to open fb0\n");
			return NULL;
		}
		alpha.alpha = 0;
		alpha.enable = 1;
		if (ioctl(fd_fb, MXCFB_SET_GBL_ALPHA, &alpha) < 0) {
			err_msg("set alpha blending failed\n");
			return NULL;
		}
		close(fd_fb);
	}
	dprintf(3, "rot_en:%d; rot_angle:%d; ipu_rot_en:%d\n", rotation.rot_en,
			rotation.rot_angle, rotation.ipu_rot_en);

	tv_mode = getenv("VPU_TV_MODE");

	if (tv_mode) {
		err = system("/bin/echo 1 > /sys/class/graphics/fb1/blank");
		if (!strcmp(tv_mode, "NTSC")) {
			err = system("/bin/echo U:720x480i-60 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else if (!strcmp(tv_mode, "PAL")) {
			err = system("/bin/echo U:720x576i-50 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else if (!strcmp(tv_mode, "720P")) {
			err = system("/bin/echo U:1280x720p-60 > /sys/class/graphics/fb1/mode");
			out = 5;
		} else {
			out = 3;
			warn_msg("VPU_TV_MODE should be set to NTSC, PAL, or 720P.\n"
				 "\tDefault display is LCD if not set this environment "
				 "or set wrong string.\n");
		}
		err = system("/bin/echo 0 > /sys/class/graphics/fb1/blank");
		if (err == -1) {
			warn_msg("set tv mode error\n");
		}
		/* make sure tvout init done */
		sleep(2);
	}

	if (rotation.rot_en) {
		if (rotation.rot_angle == 90 || rotation.rot_angle == 270) {
			i = width;
			width = height;
			height = i;
		}
		dprintf(3, "VPU rot: width = %d; height = %d\n", width, height);
	}

	disp = (struct vpu_display *)calloc(1, sizeof(struct vpu_display));
       	if (disp == NULL) {
		err_msg("falied to allocate vpu_display\n");
		return NULL;
	}

	if (!dec->cmdl->video_node) {
		if (cpu_is_mx6x())
			dec->cmdl->video_node = 17; /* fg for mx6x */
		else
			dec->cmdl->video_node = 16;
	}
	sprintf(node, "%d", dec->cmdl->video_node);
	strcpy(v4l_device, "/dev/video");
	strcat(v4l_device, node);

	fd = open(v4l_device, O_RDWR, 0);
	if (fd < 0) {
		err_msg("unable to open %s\n", v4l_device);
		goto err;
	}

	info_msg("v4l output to %s\n", v4l_device);

	if (!cpu_is_mx6x()) {
		err = ioctl(fd, VIDIOC_S_OUTPUT, &out);
		if (err < 0) {
			err_msg("VIDIOC_S_OUTPUT failed\n");
			goto err;
		}
	}

	cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	err = ioctl(fd, VIDIOC_CROPCAP, &cropcap);
	if (err < 0) {
		err_msg("VIDIOC_CROPCAP failed\n");
		goto err;
	}
	dprintf(1, "cropcap.bounds.width = %d\n\tcropcap.bound.height = %d\n\t" \
		"cropcap.defrect.width = %d\n\tcropcap.defrect.height = %d\n",
		cropcap.bounds.width, cropcap.bounds.height,
		cropcap.defrect.width, cropcap.defrect.height);

	if (rotation.ipu_rot_en == 0) {
		ratio = calculate_ratio(width, height, cropcap.bounds.width,
				cropcap.bounds.height);
		dprintf(3, "VPU rot: ratio = %d\n", ratio);
	}

	crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	crop.c.top = disp_top;
	crop.c.left = disp_left;
	crop.c.width = width / ratio;
	crop.c.height = height / ratio;

	if ((disp_width != 0) && (disp_height!= 0 )) {
		crop.c.width = disp_width;
		crop.c.height = disp_height;
	} else if (!cpu_is_mx27()) {
		crop.c.width = cropcap.bounds.width;
		crop.c.height = cropcap.bounds.height;
	}

	info_msg("Display to %d %d, top offset %d, left offset %d\n",
			crop.c.width, crop.c.height, disp_top, disp_left);

	dprintf(1, "crop.c.width/height: %d/%d\n", crop.c.width, crop.c.height);

	err = ioctl(fd, VIDIOC_S_CROP, &crop);
	if (err < 0) {
		err_msg("VIDIOC_S_CROP failed\n");
		goto err;
	}

	/* Set VDI motion algorithm. */
	if (motion_mode) {
		struct v4l2_control ctrl;
		ctrl.id = V4L2_CID_MXC_MOTION;
		if (motion_mode == 'h') {
			ctrl.value = HIGH_MOTION;
		} else if (motion_mode == 'l') {
			ctrl.value = LOW_MOTION;
		} else if (motion_mode == 'm') {
			ctrl.value = MED_MOTION;
		} else {
			ctrl.value = MED_MOTION;
			info_msg("%c unknown motion mode, medium, the default is used\n",motion_mode);
		}
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			err_msg("VIDIOC_S_CTRL failed\n");
			goto err;
		}
	}

	if (cpu_is_mx6x()) {
		/* Set rotation via new V4L2 interface on 2.6.38 kernel */
		struct v4l2_control ctrl;

		ctrl.id = V4L2_CID_ROTATE;
		if (rotation.ipu_rot_en)
			ctrl.value = rotation.rot_angle;
		else
			ctrl.value = 0;
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			err_msg("VIDIOC_S_CTRL failed\n");
			goto err;
		}
	} else if (rotation.ipu_rot_en && (rotation.rot_angle != 0)) {
		/* Set rotation via V4L2 i/f */
		struct v4l2_control ctrl;
		ctrl.id = V4L2_CID_PRIVATE_BASE;
		if (rotation.rot_angle == 90)
			ctrl.value = V4L2_MXC_ROTATE_90_RIGHT;
		else if (rotation.rot_angle == 180)
			ctrl.value = V4L2_MXC_ROTATE_180;
		else if (rotation.rot_angle == 270)
			ctrl.value = V4L2_MXC_ROTATE_90_LEFT;
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			err_msg("VIDIOC_S_CTRL failed\n");
			goto err;
		}
	} else {
		struct v4l2_control ctrl;
		ctrl.id = V4L2_CID_PRIVATE_BASE;
		ctrl.value = 0;
		err = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
		if (err < 0) {
			err_msg("VIDIOC_S_CTRL failed\n");
			goto err;
		}
	}

	if (cpu_is_mx27()) {
		fb.capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
		fb.flags = V4L2_FBUF_FLAG_PRIMARY;

		err = ioctl(fd, VIDIOC_S_FBUF, &fb);
		if (err < 0) {
			err_msg("VIDIOC_S_FBUF failed\n");
			goto err;
		}
	}

	fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;

	/*
	 * Just consider one case:
	 * (top,left) = (0,0)
	 */
	if (top || left) {
		err_msg("This case is not covered in this demo for simplicity:\n"
			"croping rectangle (top, left) != (0, 0); "
			"top/left = %d/%d\n", top, left);
		goto err;
	} else if (right || bottom) {
		if (cpu_is_mx6x()) {
			/* This is aligned with new V4L interface on 2.6.38 kernel */
			fmt.fmt.pix.width = width;
			fmt.fmt.pix.height = height;
			icrop.left = left;
			icrop.top = top;
			icrop.width = right - left;
			icrop.height = bottom - top;
			fmt.fmt.pix.priv =  (unsigned long)&icrop;
		} else {
			fmt.fmt.pix.width = right - left;
			fmt.fmt.pix.height = bottom - top;
			fmt.fmt.pix.bytesperline = width;
			off.u_offset = width * height;
			off.v_offset = off.u_offset + width * height / 4;
			fmt.fmt.pix.priv = (unsigned long) &off;
			fmt.fmt.pix.sizeimage = width * height * 3 / 2;
		}
	} else {
		fmt.fmt.pix.width = width;
		fmt.fmt.pix.height = height;
		fmt.fmt.pix.bytesperline = width;
	}
	dprintf(1, "fmt.fmt.pix.width = %d\n\tfmt.fmt.pix.height = %d\n",
				fmt.fmt.pix.width, fmt.fmt.pix.height);

	fmt.fmt.pix.field = V4L2_FIELD_ANY;

	if (dec->cmdl->mapType == LINEAR_FRAME_MAP) {
		if (dec->cmdl->chromaInterleave == 0) {
			if (dec->mjpg_fmt == MODE420)
				fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
			else if (dec->mjpg_fmt == MODE422)
				fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
			else {
				err_msg("Display cannot support this MJPG format\n");
				goto err;
			}
		} else {
			if (dec->mjpg_fmt == MODE420) {
				info_msg("Display: NV12\n");
				fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
			}
			else if (dec->mjpg_fmt == MODE422) {
				info_msg("Display: NV16\n");
				fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV16;
			}
			else {
				err_msg("Display cannot support this MJPG format\n");
				goto err;
			}
		}
	}
	else if (dec->cmdl->mapType == TILED_FRAME_MB_RASTER_MAP) {
		fmt.fmt.pix.pixelformat = IPU_PIX_FMT_TILED_NV12;
	}
	else if (dec->cmdl->mapType == TILED_FIELD_MB_RASTER_MAP) {
		fmt.fmt.pix.pixelformat = IPU_PIX_FMT_TILED_NV12F;
	}
	else {
		err_msg("Display cannot support mapType = %d\n", dec->cmdl->mapType);
		goto err;
	}
	err = ioctl(fd, VIDIOC_S_FMT, &fmt);
	if (err < 0) {
		err_msg("VIDIOC_S_FMT failed\n");
		goto err;
	}

	err = ioctl(fd, VIDIOC_G_FMT, &fmt);
	if (err < 0) {
		err_msg("VIDIOC_G_FMT failed\n");
		goto err;
	}

	reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	reqbuf.memory = V4L2_MEMORY_MMAP;
	reqbuf.count = nframes;

	err = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
	if (err < 0) {
		err_msg("VIDIOC_REQBUFS failed\n");
		goto err;
	}

	if (reqbuf.count < nframes) {
		err_msg("VIDIOC_REQBUFS: not enough buffers\n");
		goto err;
	}

	for (i = 0; i < nframes; i++) {
		struct v4l2_buffer buffer = {0};
		struct v4l_buf *buf;

		buf = calloc(1, sizeof(struct v4l_buf));
		if (buf == NULL) {
			v4l_free_bufs(i, disp);
			goto err;
		}

		disp->buffers[i] = buf;

		buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
		buffer.memory = V4L2_MEMORY_MMAP;
		buffer.index = i;

		err = ioctl(fd, VIDIOC_QUERYBUF, &buffer);
		if (err < 0) {
			err_msg("VIDIOC_QUERYBUF: not enough buffers\n");
			v4l_free_bufs(i, disp);
			goto err;
		}
		buf->start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
				MAP_SHARED, fd, buffer.m.offset);

		if (cpu_is_mx6x()) {
			/*
			 * Workaround for new V4L interface change, this change
			 * will be removed after V4L driver is updated for this.
			 * Need to call QUERYBUF ioctl again after mmap.
			 */
			err = ioctl(fd, VIDIOC_QUERYBUF, &buffer);
			if (err < 0) {
				err_msg("VIDIOC_QUERYBUF: not enough buffers\n");
				v4l_free_bufs(i, disp);
				goto err;
			}
		}
		buf->offset = buffer.m.offset;
		buf->length = buffer.length;
		dprintf(3, "V4L2buf phy addr: %08x, size = %d\n",
				    (unsigned int)buf->offset, buf->length);

		if (buf->start == MAP_FAILED) {
			err_msg("mmap failed\n");
			v4l_free_bufs(i, disp);
			goto err;
		}

	}

	disp->fd = fd;
	disp->nframes = nframes;

	/*
	 * Use environment VIDEO_PERFORMANCE_TEST to select different mode.
	 * When doing performance test, video decoding and display are in different
	 * threads and default display fps is controlled by cmd. Display will
	 * show the frame immediately if user doesn't input fps with -a option.
	 * This is different from normal unit test.
	 */
	test_mode = getenv("VIDEO_PERFORMANCE_TEST");
	if (test_mode && !strcmp(test_mode, "1") && (dec->cmdl->dst_scheme == PATH_V4L2))
		vpu_v4l_performance_test = 1;

	if (vpu_v4l_performance_test) {
		dec->disp = disp;
		sem_init(&disp->avaiable_decoding_frame, 0,
			    dec->regfbcount - dec->minfbcount);
		sem_init(&disp->avaiable_dequeue_frame, 0, 0);
		pthread_mutex_init(&v4l_mutex, NULL);
		/* start v4l disp loop thread */
		pthread_create(&(disp->v4l_disp_loop_thread), NULL,
				    (void *)v4l_disp_loop_thread, (void *)dec);
	}

	return disp;
err:
	close(fd);
	free(disp);
	return NULL;
}