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; }
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; }
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; }