/* * Initialization routine for the 3rd party display driver */ static enum OMAP_ERROR create_display_devices(void) { PFN_CMD_PROC pfnCmdProcList[OMAP_DC_CMD_COUNT]; IMG_UINT32 aui32SyncCountList[OMAP_DC_CMD_COUNT][2]; int i; unsigned int bytes_to_alloc; DEBUG_PRINTK("Initializing 3rd party display driver"); /* Ask for the number of displays available */ omap_display_init(); /* TODO: allow more displays */ display_devices_count = 1; // omap_display_count(); DEBUG_PRINTK("Found %i displays", display_devices_count); /* * Obtain the function pointer for the jump table from kernel * services to fill it with the function pointers that we want */ if(get_pvr_dc_jtable ("PVRGetDisplayClassJTable", &pfnGetPVRJTable) != OMAP_OK) { ERROR_PRINTK("Unable to get the function to get the" " jump table display->services"); return OMAP_ERROR_INIT_FAILURE; } /* * Allocate the display device structures, one per display available */ bytes_to_alloc = sizeof(struct OMAP_DISP_DEVINFO) * display_devices_count; pDisplayDevices = (struct OMAP_DISP_DEVINFO *) kmalloc( bytes_to_alloc, GFP_KERNEL); if(!pDisplayDevices) { pDisplayDevices = NULL; ERROR_PRINTK("Out of memory"); return OMAP_ERROR_OUT_OF_MEMORY; } memset(pDisplayDevices, 0, bytes_to_alloc); /* * Initialize each display device */ for(i = 0; i < display_devices_count; i++) { struct omap_display_device *display; struct OMAP_DISP_DEVINFO * psDevInfo; enum omap_display_id id; psDevInfo = &pDisplayDevices[i]; psDevInfo->display = 0; id = OMAP_DISPID_VIRTUAL; /* * TODO: Modify this to allow primary, secondary, * not only virtual */ #if 0 switch(i) { case 0: id = OMAP_DISPID_PRIMARY; break; case 1: id = OMAP_DISPID_SECONDARY; break; case 2: id = OMAP_DISPID_TERTIARY; break; case 3: id = OMAP_DISPID_VIRTUAL; break; default: ERROR_PRINTK("Invalid display type %i", i); BUG(); } #endif display = omap_display_get(id); if(!display) continue; if(init_display_device(psDevInfo, display) != OMAP_OK) { ERROR_PRINTK("Unable to initialize display '%s' type" " %u", display->name, display->id); continue; #if 0 kfree(pDisplayDevices); pDisplayDevices = NULL; return OMAP_ERROR_INIT_FAILURE; #endif } /* * Populate each display device structure */ if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable)) { ERROR_PRINTK("Unable to get the jump table" " display->services for display '%s'", display->name); return OMAP_ERROR_INIT_FAILURE; } /* Populate the function table that services will use */ psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE); psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice; psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice; psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats; psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims; psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer; psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo; psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr; psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain; psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain; psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect; psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect; psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey; psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey; psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers; psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer; psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem; psDevInfo->sDCJTable.pfnSetDCState = SetDCState; /* Register the display device */ if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice( &psDevInfo->sDCJTable, (IMG_UINT32*) &psDevInfo->ulDeviceID) != PVRSRV_OK) { ERROR_PRINTK("Unable to register the jump table" " services->display"); return OMAP_ERROR_DEVICE_REGISTER_FAILED; } DEBUG_PRINTK("Display '%s' registered with the GPU with" " id %lu", display->name, psDevInfo->ulDeviceID); /* * Register the ProcessFlip function to notify when a frame is * ready to be flipped */ pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip; aui32SyncCountList[DC_FLIP_COMMAND][0] = 0; aui32SyncCountList[DC_FLIP_COMMAND][1] = 2; if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList( psDevInfo->ulDeviceID, &pfnCmdProcList[0], aui32SyncCountList, OMAP_DC_CMD_COUNT) != PVRSRV_OK) { ERROR_PRINTK("Unable to register callback for " "ProcessFlip command"); return OMAP_ERROR_CANT_REGISTER_CALLBACK; } } return OMAP_OK; }
int main(int argc, char *argp[]) { char shortoptions[] = "r:w:u:f:i:p:h:x:c:"; int mode = O_RDWR,c,ret,index, display_index; int preview_fd, rsz_fd, capt_fd, display_fd, dev_idx; unsigned int oper_mode, user_mode=IMP_MODE_CONTINUOUS; struct rsz_channel_config rsz_chan_config; struct rsz_continuous_config rsz_cont_config; // continuous mode int level; int width = 720, height = 480; int *capbuf_addr; fd_set fds; struct timeval tv; int r; int quit=0; struct timezone zone; int frame_count=0; static int captFrmCnt = 0; struct v4l2_buffer cap_buf, disp_buf; int temp_index; for(;;) { c = getopt_long(argc, argp, shortoptions, NULL, (void *)&index); if(-1 == c) break; switch(c) { case 'f': out_format = atoi(optarg); if (out_format < 0 || out_format > 1) { printf("Choose 0 - UYVY 1 - NV12 for output pix format\n"); exit(1); } break; case 'p': case 'P': printfn = atoi(optarg); break; case 'h': half_fps = atoi(optarg); break; case 'x': disp_second_output = atoi(optarg); break; case 'c': en_crop = atoi(optarg); break; case 'r': resize = atoi(optarg); break; case 'w': rsz_width = atoi(optarg); break; case 'u': rsz_height = atoi(optarg); break; case 'i': case 'I': input_index = atoi(optarg); if (input_index > 2) printf("choose index 0 for Composite," " 1 - Svideo or 2 - component\n"); break; default: usage(); exit(1); } } if (allocate_user_buffers() < 0) { printf("Unable to Allocate user buffers\n"); exit(1); } // intialize resizer in continuous mode rsz_fd = init_resizer(user_mode); if (rsz_fd < 0) { exit(1); } // initialize previewer in continuous mode preview_fd = init_previewer(user_mode); if (preview_fd < 0) { close(rsz_fd); exit(1); } capt_fd = init_camera_capture(); if (capt_fd < 0) { close(preview_fd); close(rsz_fd); exit(1); } if (!out_format) second_output_offset = in_width * in_height * 2; else second_output_offset = ALIGN(in_width ,32) * in_height * 1.5; second_output_offset = ALIGN(second_output_offset, 4096); printf("Second output offset = %d\n", second_output_offset); display_fd = init_display_device(0); if (display_fd < 0) { close(preview_fd); close(rsz_fd); close(capt_fd); exit(1); } printf("Initialized display\n"); #if 0 if (ioctl(preview_fd, PREV_DUMP_HW_CONFIG, &level) < 0) { perror("Error in debug ioctl\n"); cleanup_capture(capt_fd); cleanup_display(display_fd); close(preview_fd); close(rsz_fd); exit(1); } #endif while (!quit) { unsigned long temp; CLEAR(cap_buf); CLEAR(disp_buf); try1: disp_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; disp_buf.memory = V4L2_MEMORY_USERPTR; ret = ioctl(display_fd, VIDIOC_DQBUF, &disp_buf); if (ret < 0) { if (errno == EAGAIN) { goto try1; } perror("VIDIOC_DQBUF for display failed\n"); return ret; } cap_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; cap_buf.memory = V4L2_MEMORY_USERPTR; try2: ret = ioctl(capt_fd, VIDIOC_DQBUF, &cap_buf); if (ret < 0) { if (errno == EAGAIN) { goto try2; } perror("VIDIOC_DQBUF for capture failed\n"); return ret; } temp = cap_buf.m.userptr; if (disp_second_output) { cap_buf.m.userptr = disp_buf.m.userptr - second_output_offset; disp_buf.m.userptr = temp + second_output_offset; } else { cap_buf.m.userptr = disp_buf.m.userptr; disp_buf.m.userptr = temp; } //printf("disp_buf.m.userptr = %x\n", disp_buf.m.userptr); ret = ioctl(capt_fd, VIDIOC_QBUF, &cap_buf); if (ret < 0) { perror("VIDIOC_QBUF for capture failed\n"); return ret; } ret = ioctl(display_fd, VIDIOC_QBUF, &disp_buf); if (ret < 0) { perror("VIDIOC_QBUF for display failed\n"); return ret; } if (captFrmCnt == 0) prev_ts = (cap_buf.timestamp.tv_sec*1000000) + cap_buf.timestamp.tv_usec; else { curr_ts = (cap_buf.timestamp.tv_sec*1000000) + cap_buf.timestamp.tv_usec; fp_period = curr_ts - prev_ts; if (captFrmCnt == 1) { fp_period_max = fp_period_min = fp_period_average = fp_period; } else { /* calculate jitters and average */ if (fp_period > fp_period_max) fp_period_max = fp_period; if (fp_period < fp_period_min) fp_period_min = fp_period; fp_period_average = ((fp_period_average * captFrmCnt) + fp_period)/(captFrmCnt + 1); } prev_ts = curr_ts; } captFrmCnt++; if (printfn) { printf("frame:%5u, ", captFrmCnt); printf("buf.timestamp:%lu:%lu\n", cap_buf.timestamp.tv_sec, cap_buf.timestamp.tv_usec); } if (captFrmCnt > 5000) break; } printf("Cleaning capture\n"); cleanup_capture(capt_fd); printf("Cleaning display\n"); cleanup_display(display_fd); printf("Cleaning display - end\n"); close(preview_fd); printf("closing preview- end\n"); close(rsz_fd); printf("closing resize - end\n"); exit(0); }