VSFlowReturn _configDeinterlace (void *vshandle, void *config) { VS_FLOW ("Fun %s in\n", __FUNCTION__); VideoSurface *vs; vs = (VideoSurface *) vshandle; int *mode = (int *) config; VS_LOCK (gVSlock); VS_MESSAGE ("set deinterlace mode %d\n", *mode); if (*mode) { INPUT_ENABLE_DEINTERLACE (&vs->itask); } else { INPUT_DISABLE_DEINTERLACE (&vs->itask); } INPUT_DEINTERLACE_MODE (&vs->itask) = *mode; VS_UNLOCK (gVSlock); VS_FLOW ("Fun %s out\n", __FUNCTION__); return VS_FLOW_OK; }
VSFlowReturn _configMasterVideoLayer(void * vshandle, void * config) { VS_FLOW("Fun %s in\n", __FUNCTION__); VideoSurface * vs; vs = (VideoSurface *)vshandle; if (NEXTSURFACE(vs)==NULL) return VS_FLOW_OK; VideoDevice * vd=SURFACE2DEVICE(vs); VS_LOCK(gVSlock); _removeVideoSurfaceFromDevice(vd,vs); _addVideoSurface2Device(vd,vs); _refreshOnDevice(vd); VS_UNLOCK(gVSlock); VS_FLOW("Fun %s out\n", __FUNCTION__); return VS_FLOW_OK; }
/*============================================================================= FUNCTION: render2VideoSurface DESCRIPTION: This function render a new frame on specific video surface It also will refresh other video surfaces in same video device automaticallly. ==============================================================================*/ VSFlowReturn render2VideoSurface(void * vshandle, SourceFrame * frame, SourceFmt * srcfmt) { VS_FLOW("Fun %s in\n", __FUNCTION__); VideoDevice * vd; VideoSurface * vsurface, *vsurface1; Updated updated; if ((vshandle==NULL)||(frame==NULL)){ VS_ERROR("%s: parameters error!\n", __FUNCTION__); return VS_FLOW_PARAMETER_ERROR; } vsurface = (VideoSurface *)vshandle; if (vsurface->status == VS_STATUS_INVISIBLE) /* no need to render */ return VS_FLOW_OK; vsurface->paddr = frame->paddr; vsurface->rendmask = 0;/*clear mask*/ vd = SURFACE2DEVICE(vsurface); if (sem_trywait(gVSlock)) return VS_FLOW_PENDING; vsurface1 = DEVICE2HEADSURFACE(vd); memset((void *)(&updated), 0, sizeof(Updated)); while(vsurface1){ if (_needRender(vsurface1, &updated, vd->renderidx)){ _renderSuface(vsurface1, vd, &updated); } vsurface1 = NEXTSURFACE(vsurface1); }; _FlipOnDevice(vd); #if 0 /* no need to sleep anymore */ if (vd->cnt>1) usleep(10000); #endif done: VS_UNLOCK(gVSlock); VS_FLOW("Fun %s out\n", __FUNCTION__); return VS_FLOW_OK; err: return VS_FLOW_ERROR; }
VSFlowReturn _configMasterVideoSurface(void * vshandle, void * config) { VS_FLOW("Fun %s in\n", __FUNCTION__); DestinationFmt * des = (DestinationFmt *)config; VideoSurface * vs; SourceFmt src; vs = (VideoSurface *)vshandle; VS_MESSAGE("reconfig win from "WIN_FMT" to "WIN_FMT"\n", WIN_ARGS(&vs->desfmt.rect), WIN_ARGS(&des->rect)); VideoDevice * vd=SURFACE2DEVICE(vs); VS_LOCK(gVSlock); vs->desfmt = *des; vs->outside = _adjustDestRect(&des->rect, vd); vs->adjustdesrect = des->rect; if (NEXTSURFACE(vs)){ _removeVideoSurfaceFromDevice(vd,vs); _addVideoSurface2Device(vd,vs); } _clearVideoSurfaceBackground(vd, vs); if (_checkOnDevice(vd)){ _reconfigAllVideoSurfaces(vd); _setDeviceConfig(vd); }else{ _initVSIPUTask(vs); } if (vd->setalpha) _setAlpha(vd); vs->mainframeupdate = 1; if (vs->itask.mode){ _reconfigSubFrameBuffer(vs); vs->mainframeupdate = 0; _updateSubFrame(vs); } _refreshOnDevice(vd); VS_UNLOCK(gVSlock); VS_FLOW("Fun %s out\n", __FUNCTION__); return VS_FLOW_OK; }
int _setDeviceConfig (VideoDevice * vd) { VS_FLOW ("Fun %s in\n", __FUNCTION__); struct fb_var_screeninfo fb_var; struct fb_fix_screeninfo fb_fix; struct mxcfb_pos pos; Rect *rect; int i; int fd = _getDevicefd (vd); /* Workaround for ipu hardware, it need set to 0,0 before change another offset */ pos.x = 0; pos.y = 0; VS_IOCTL (fd, MXCFB_SET_OVERLAY_POS, here1, &pos); here1: VS_IOCTL (fd, FBIOBLANK, done, FB_BLANK_POWERDOWN); //VS_MESSAGE("Set device win"WIN_FMT"\n", WIN_ARGS(&vd->disp)); rect = &vd->disp; VS_IOCTL (fd, FBIOGET_VSCREENINFO, done, &fb_var); fb_var.xres = RECT_WIDTH (rect); fb_var.xres_virtual = fb_var.xres; fb_var.yres = RECT_HEIGHT (rect); fb_var.yres_virtual = fb_var.yres * FB_NUM_BUFFERS; fb_var.activate |= FB_ACTIVATE_FORCE; fb_var.nonstd = vd->fmt; fb_var.bits_per_pixel = fmt2bit (vd->fmt); VS_IOCTL (fd, FBIOPUT_VSCREENINFO, done, &fb_var); VS_IOCTL (fd, FBIOGET_VSCREENINFO, done, &fb_var); VS_IOCTL (fd, FBIOGET_FSCREENINFO, done, &fb_fix); pos.x = vd->disp.left; pos.y = vd->disp.top; VS_IOCTL (fd, MXCFB_SET_OVERLAY_POS, here2, &pos); here2: VS_IOCTL (fd, FBIOBLANK, done, FB_BLANK_UNBLANK); for (i = 0; i < FB_NUM_BUFFERS; i++) { vd->bufaddr[i] = (void *) (fb_fix.smem_start + fb_var.yres * fb_fix.line_length * i); } if (fmt2cs (vd->fmt) == 0) { _clearBackground (vd, NULL); } done: return 0; }
VSLock * _getAndLockVSLock (int flag) { VS_FLOW ("Fun %s in\n", __FUNCTION__); VSLock *lock; int oflag = 0; if (flag & VS_IPC_CREATE) oflag |= O_CREAT; if (flag & VS_IPC_EXCL) oflag |= O_EXCL; umask (0); lock = sem_open (VS_LOCK_NAME, oflag, 0666, 1); if (SEM_FAILED == lock) { VS_ERROR ("%s: can not get lock %s!\n", __FUNCTION__, VS_LOCK_NAME); goto err; } VS_LOCK (lock); return lock; err: return NULL; }
int queryVideoDevice (int idx, VideoDeviceDesc * vd_desc) { VS_FLOW ("Fun %s in\n", __FUNCTION__); VideoDevice *vd; if ((idx < 0) || (idx >= VD_MAX) || (vd_desc == NULL)) goto bail; if (gVSctl == NULL) { gVSlock = _getAndLockVSLock (VS_IPC_CREATE); if (gVSlock == NULL) { VS_ERROR ("Can not create/open ipc semphone!\n"); goto bail; } gVSctl = _getVSControl (VS_IPC_CREATE); if (gVSctl == NULL) { VS_ERROR ("Can not create/open ipc sharememory!\n"); VS_UNLOCK (gVSlock); goto bail; } } else { VS_LOCK (gVSlock); } vd = &gVSctl->devices[idx]; vd_desc->resx = vd->resX; vd_desc->resy = vd->resY; if (vd->fbidx >= 0) { int i; vd_desc->devid = vd->fbidx; vd_desc->custom_mode_num = vd->mode_num; memcpy (vd_desc->name, vd->name, NAME_LEN); for (i = 0; i < vd_desc->custom_mode_num; i++) { vd_desc->modes[i] = vd->modes[i]; } } else { VS_UNLOCK (gVSlock); goto bail; } VS_UNLOCK (gVSlock); return 0; bail: return -1; }
void video_surface_destroy(void) { VS_FLOW("Fun %s in\n", __FUNCTION__); VideoSurface * vs = gvslocal, *vsnext; while(vs){ vsnext = vs->next; _destroyVideoSurface(vs, 1); vs = vsnext; } }
static void _reconfigAllVideoSurfaces (VideoDevice * vd) { VS_FLOW ("Fun %s in\n", __FUNCTION__); VideoSurface *vs = DEVICE2HEADSURFACE (vd); while (vs) { _initVSIPUTask (vs); vs = NEXTSURFACE (vs); } }
static int _checkOnDevice (VideoDevice * vd) { VS_FLOW ("Fun %s in\n", __FUNCTION__); int reconfig = ((vd->init == 0) ? 1 : 0); if (reconfig) { vd->disp.left = 0; vd->disp.top = 0; vd->disp.right = vd->resX; vd->disp.bottom = vd->resY; } return reconfig; }
static void _removeVideoSurfaceFromDevice (VideoDevice * vd, VideoSurface * vs) { VS_FLOW ("Fun %s in\n", __FUNCTION__); VideoSurface *pvs = DEVICE2HEADSURFACE (vd); if (pvs == vs) { SET_DEVICEHEADSURFACE (vd, NEXTSURFACE (vs)); } else { while (NEXTSURFACE (pvs) != vs) { pvs = NEXTSURFACE (pvs); } SET_NEXTSURFACE (pvs, NEXTSURFACE (vs)); } }
VideoSurfacesControl * _getVSControl (int flag) { VS_FLOW ("Fun %s in\n", __FUNCTION__); VideoSurfacesControl *control; int shmid; struct stat shmStat; int ret; int oflag = O_RDWR; if (flag & VS_IPC_CREATE) oflag |= O_CREAT; if (flag & VS_IPC_EXCL) oflag |= O_EXCL; shmid = shm_open (VS_SHMEM_NAME, oflag, 0666); if (shmid == -1) { VS_ERROR ("%s: can not get share memory %s!\n", __FUNCTION__, VS_SHMEM_NAME); goto err; } ret = ftruncate (shmid, (off_t) (3 * sizeof (VideoSurfacesControl))); if (ret < 0) { goto err; } /* Connect to the shm */ fstat (shmid, &shmStat); control = (VideoSurfacesControl *) mmap (NULL, shmStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0); if ((control == NULL) || (control == MAP_FAILED)) { VS_ERROR ("%s: can not mmap share memory %d!\n", __FUNCTION__, shmid); goto err; } if (control->init == 0) { _initVSControl (control); control->init = 1; } return control; err: return NULL; }
static void _addVideoSurface2Device (VideoDevice * vd, VideoSurface * vs) { VS_FLOW ("Fun %s in\n", __FUNCTION__); VideoSurface *pvs = DEVICE2HEADSURFACE (vd); vs->nextid = 0; if (pvs) { while (NEXTSURFACE (pvs)) pvs = NEXTSURFACE (pvs); SET_NEXTSURFACE (pvs, vs); } else { SET_DEVICEHEADSURFACE (vd, vs); } }
int _needRender (VideoSurface * curSurf, Updated * updated, int renderidx) { VS_FLOW ("Fun %s in\n", __FUNCTION__); if (curSurf->paddr == NULL) return 0; if (curSurf->status == VS_STATUS_INVISIBLE) return 0; if ((curSurf->rendmask & (1 << renderidx)) == 0) return 1; if ((updated->updated) && (OVERLAPED_RECT ((&(curSurf->adjustdesrect)), (&updated->rect)))) return 1; return 0; }
void _initVSIPUTask (VideoSurface * surf) { VideoDevice *vd = SURFACE2DEVICE (surf); IPUTaskOne *t1 = &surf->itask; Rect *rect = &(surf->srcfmt.croprect.win), *desrect; VS_FLOW ("Fun %s in\n", __FUNCTION__); desrect = &(surf->adjustdesrect); if (surf->outside & VS_INVISIBLE) { surf->status = VS_STATUS_INVISIBLE; return; } surf->status = VS_STATUS_VISIBLE; INPUT_FORMAT (t1) = surf->srcfmt.fmt; INPUT_WIDTH (t1) = surf->srcfmt.croprect.width; INPUT_HEIGHT (t1) = surf->srcfmt.croprect.height; INPUT_CROP_X (t1) = rect->left; INPUT_CROP_Y (t1) = rect->top; INPUT_CROP_WIDTH (t1) = RECT_WIDTH (rect); INPUT_CROP_HEIGHT (t1) = RECT_HEIGHT (rect); if (surf->outside) { /* output outside of screen, need crop in input */ int xx[4] = { 0, 0, 0, 0 }; Rect *origrect = &surf->desfmt.rect; int x_len, y_len; if (surf->desfmt.rot <= ROTATION_180_CLOCKWISE) { x_len = RECT_WIDTH (rect); y_len = RECT_HEIGHT (rect); } else { y_len = RECT_WIDTH (rect); x_len = RECT_HEIGHT (rect); } if (surf->outside & VS_LEFT_OUT) { xx[0] = (DEVICE_LEFT_EDGE - origrect->left) * x_len / RECT_WIDTH (origrect); xx[0] = ALIGNLEFT8 (xx[0]); } if (surf->outside & VS_RIGHT_OUT) { xx[1] = (origrect->right - vd->resX) * x_len / RECT_WIDTH (origrect); xx[1] = ALIGNLEFT8 (xx[1]); } if (surf->outside & VS_TOP_OUT) { xx[2] = (DEVICE_TOP_EDGE - origrect->top) * y_len / RECT_HEIGHT (origrect); xx[2] = ALIGNLEFT8 (xx[2]); } if (surf->outside & VS_BOTTOM_OUT) { xx[3] = (origrect->bottom - vd->resY) * y_len / RECT_HEIGHT (origrect); xx[3] = ALIGNLEFT8 (xx[3]); } if (surf->desfmt.rot <= ROTATION_180_CLOCKWISE) { INPUT_CROP_WIDTH (t1) -= (xx[0] + xx[1]); INPUT_CROP_HEIGHT (t1) -= (xx[2] + xx[3]); } else { INPUT_CROP_WIDTH (t1) -= (xx[2] + xx[3]); INPUT_CROP_HEIGHT (t1) -= (xx[0] + xx[1]); } INPUT_CROP_X (t1) += xx[g_vstable[surf->desfmt.rot][0]]; INPUT_CROP_Y (t1) += xx[g_vstable[surf->desfmt.rot][1]]; } OUTPUT_FORMAT (t1) = vd->fmt; OUTPUT_WIDTH (t1) = vd->disp.right - vd->disp.left; OUTPUT_HEIGHT (t1) = vd->disp.bottom - vd->disp.top; OUTPUT_CROP_X (t1) = desrect->left - vd->disp.left; OUTPUT_CROP_Y (t1) = desrect->top - vd->disp.top; OUTPUT_CROP_WIDTH (t1) = desrect->right - desrect->left; OUTPUT_CROP_HEIGHT (t1) = desrect->bottom - desrect->top; OUTPUT_ROTATION (t1) = surf->desfmt.rot; if ((INPUT_CROP_WIDTH (t1) < 16) || (INPUT_CROP_HEIGHT (t1) < 16) || (OUTPUT_CROP_WIDTH (t1) < 16) || (OUTPUT_CROP_HEIGHT (t1) < 16)) { surf->status = VS_STATUS_INVISIBLE; } }
void _initVSIPUTask(VideoSurface * surf) { VS_FLOW("Fun %s in\n", __FUNCTION__); VideoDevice * vd = SURFACE2DEVICE(surf); ipu_lib_input_param_t * input = &surf->itask.input; Rect * rect = &(surf->srcfmt.croprect.win), *desrect; desrect = &(surf->adjustdesrect); input->fmt = surf->srcfmt.fmt; input->width = surf->srcfmt.croprect.width; input->height = surf->srcfmt.croprect.height; if (surf->outside==0){ input->input_crop_win.pos.x = rect->left; input->input_crop_win.pos.y = rect->top; input->input_crop_win.win_w = RECT_WIDTH(rect); input->input_crop_win.win_h = RECT_HEIGHT(rect); }else{ /* output outside of screen, need crop in input */ int xl=0, xr=0, xt=0, xb=0; Rect * origrect = &surf->desfmt.rect; if (surf->outside&VS_LEFT_OUT){ xl = (DEVICE_LEFT_EDGE-origrect->left)*RECT_WIDTH(rect)/RECT_WIDTH(origrect); ALIGNLEFT8(xl); } if (surf->outside&VS_RIGHT_OUT){ xr = (origrect->right-vd->resX)*RECT_WIDTH(rect)/RECT_WIDTH(origrect); ALIGNLEFT8(xr); } if (surf->outside&VS_TOP_OUT){ xt = (DEVICE_TOP_EDGE-origrect->top)*RECT_HEIGHT(rect)/RECT_HEIGHT(origrect); ALIGNLEFT8(xt); } if (surf->outside&VS_BOTTOM_OUT){ xb = (origrect->bottom-vd->resY)*RECT_HEIGHT(rect)/RECT_HEIGHT(origrect); ALIGNLEFT8(xb); } input->input_crop_win.pos.x = rect->left+xl; input->input_crop_win.pos.y = rect->top+xt; input->input_crop_win.win_w = RECT_WIDTH(rect)-xl-xr; input->input_crop_win.win_h = RECT_HEIGHT(rect)-xt-xb; } input->user_def_paddr[0] = input->user_def_paddr[1] = 0; ipu_lib_output_param_t * output = &surf->itask.output; output->fmt = vd->fmt; output->width = vd->disp.right-vd->disp.left; output->height = vd->disp.bottom-vd->disp.top; output->output_win.pos.x = desrect->left-vd->disp.left; output->output_win.pos.y = desrect->top-vd->disp.top; output->output_win.win_w = desrect->right-desrect->left; output->output_win.win_h = desrect->bottom-desrect->top; output->user_def_paddr[0] = output->user_def_paddr[1] = 0; output->rot = surf->desfmt.rot; }
/*============================================================================= FUNCTION: createVideoSurface DESCRIPTION: This function create a video surface. ==============================================================================*/ void * createVideoSurface (int devid, int mode_idx, SourceFmt * src, DestinationFmt * des) { VS_FLOW ("Fun %s in\n", __FUNCTION__); VideoSurfacesControl *vc; VideoSurface *vs = NULL; VideoDevice *vd; int i; if (_checkSource (src)) { VS_ERROR ("source fmt error\n"); goto err; } if ((des == NULL) || (src == NULL)) { VS_ERROR ("%s: parameters error!\n", __FUNCTION__); goto err; } if (gVSctl == NULL) { gVSlock = _getAndLockVSLock (VS_IPC_CREATE); if (gVSlock == NULL) { VS_ERROR ("Can not create/open ipc semphone!\n"); goto err; } gVSctl = _getVSControl (VS_IPC_CREATE); if (gVSctl == NULL) { VS_ERROR ("Can not create/open ipc sharememory!\n"); VS_UNLOCK (gVSlock); goto err; } } else { VS_LOCK (gVSlock); } vc = gVSctl; if ((vd = _getDevicebyDevID (devid)) == NULL) { VS_ERROR ("Can not find dev id %d!\n", devid); VS_UNLOCK (gVSlock); goto err; } if (vd->cnt >= vd->vsmax) { VS_UNLOCK (gVSlock); VS_ERROR ("%s: max surfaces on device support on device%d exceeded!\n", __FUNCTION__, devid); goto err; } for (i = 0; i < VS_MAX; i++) { if (vc->surfaces[i].status == VS_STATUS_IDLE) { break; } } if (i == VS_MAX) { VS_UNLOCK (gVSlock); VS_ERROR ("%s: max surface support exceeded!\n", __FUNCTION__); goto err; } vs = &vc->surfaces[i]; vs->status = VS_STATUS_VISIBLE; vs->vd_id = vd->id; vs->srcfmt = *src; vs->desfmt = *des; vs->itask.mode = 0; vs->mainframeupdate = 1; memset (&vs->itask, 0, sizeof (IPUTaskOne)); if (vd->init == 0) { if (_initVideoDevice (vd, mode_idx)) { VS_UNLOCK (gVSlock); VS_ERROR ("%s: error config!\n", __FUNCTION__); goto err; } } vs->outside = _adjustDestRect (&des->rect, vd); vs->adjustdesrect = des->rect; VS_MESSAGE ("VS%d created. in fmt[" FOURCC_FMT "] win" WIN_FMT " out win" WIN_FMT "\n", vs->id - 1, FOURCC_ARGS (src->fmt), WIN_ARGS (&src->croprect.win), WIN_ARGS (&vs->desfmt.rect)); vs->next = gvslocal; gvslocal = vs; vd->cnt++; if (vd->cnt == 1) { _openDevice (vd); } _addVideoSurface2Device (vd, vs); if (_checkOnDevice (vd)) { _reconfigAllVideoSurfaces (vd); _setDeviceConfig (vd); } vd->init = 1; _initVSIPUTask (vs); if (vd->setalpha) _setAlpha (vd); VS_UNLOCK (gVSlock); VS_FLOW ("Fun %s out\n", __FUNCTION__); return (void *) vs; err: if (vs) { vs->status = VS_STATUS_IDLE; } return NULL; }