static Status Validate(Display *dpy, XvPortID port, int surface_type_id, unsigned int width, unsigned int height, int flags, bool *found_port, int *screen, int *chroma_format, int *mc_type, int *surface_flags, unsigned short *subpic_max_w, unsigned short *subpic_max_h) { bool found_surface = false; XvAdaptorInfo *adaptor_info; unsigned int num_adaptors; int num_types; unsigned int max_width = 0, max_height = 0; Status ret; assert(dpy); assert(found_port); assert(screen); assert(chroma_format); assert(mc_type); assert(surface_flags); assert(subpic_max_w); assert(subpic_max_h); *found_port = false; for (int i = 0; i < XScreenCount(dpy); ++i) { ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info); if (ret != Success) return ret; for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) { for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) { XvMCSurfaceInfo *surface_info; if (adaptor_info[j].base_id + k != port) continue; *found_port = true; surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types); if (!surface_info) { XvFreeAdaptorInfo(adaptor_info); return BadAlloc; } for (int l = 0; l < num_types && !found_surface; ++l) { if (surface_info[l].surface_type_id != surface_type_id) continue; found_surface = true; max_width = surface_info[l].max_width; max_height = surface_info[l].max_height; *chroma_format = surface_info[l].chroma_format; *mc_type = surface_info[l].mc_type; *surface_flags = surface_info[l].flags; *subpic_max_w = surface_info[l].subpicture_max_width; *subpic_max_h = surface_info[l].subpicture_max_height; *screen = i; XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \ "[XvMC] screen=%u, port=%u\n" \ "[XvMC] id=0x%08X\n" \ "[XvMC] max width=%u, max height=%u\n" \ "[XvMC] chroma format=0x%08X\n" \ "[XvMC] acceleration level=0x%08X\n" \ "[XvMC] flags=0x%08X\n" \ "[XvMC] subpicture max width=%u, max height=%u\n", i, port, surface_type_id, max_width, max_height, *chroma_format, *mc_type, *surface_flags, *subpic_max_w, *subpic_max_h); } free(surface_info); } } XvFreeAdaptorInfo(adaptor_info); } if (!*found_port) { XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n"); return XvBadPort; } if (!found_surface) { XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n"); return BadMatch; } if (width > max_width || height > max_height) { XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n", width, height, max_width, max_height); return BadValue; } if (flags != XVMC_DIRECT && flags != 0) { XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags); return BadValue; } return Success; }
static Bool GetPortId(Display *dpy, XvPortID *portID, int *surface_type) { int i, j, k, numAdapt, numTypes, eventBase, errorBase; XvMCSurfaceInfo *surfaceInfo; XvAdaptorInfo *info; Bool result = 0; if(!XvMCQueryExtension(dpy, &eventBase, &errorBase)) return 0; if(Success != XvQueryAdaptors(dpy,DefaultRootWindow(dpy),&numAdapt,&info)) return 0; for(i = 0; i < numAdapt; i++) { if(info[i].type & XvImageMask) { surfaceInfo = XvMCListSurfaceTypes(display, info[i].base_id, &numTypes); if(surfaceInfo) { for(j = 0; j < numTypes; j++) { if((surfaceInfo[j].chroma_format == XVMC_CHROMA_FORMAT_420) && (surfaceInfo[j].max_width >= coded_picture_width) && (surfaceInfo[j].max_height >= coded_picture_height) && ((surfaceInfo[j].mc_type == (XVMC_MOCOMP | XVMC_MPEG_2)) || (surfaceInfo[j].mc_type == (XVMC_IDCT | XVMC_MPEG_2)))) { if(use_idct != -1) { if(use_idct == 1) { if(surfaceInfo[j].mc_type == (XVMC_MOCOMP | XVMC_MPEG_2)) continue; } else { if(surfaceInfo[j].mc_type == (XVMC_IDCT | XVMC_MPEG_2)) continue; } } for(k = 0; k < info[i].num_ports; k++) { /* try to grab a port */ if(Success == XvGrabPort(dpy, info[i].base_id + k, CurrentTime)) { *portID = info[i].base_id + k; *surface_type = surfaceInfo[j].surface_type_id; result = 1; break; } } if(result) { if(surfaceInfo[j].flags & XVMC_INTRA_UNSIGNED) unsignedIntra = 1; if(surfaceInfo[j].mc_type == (XVMC_IDCT | XVMC_MPEG_2)) useIDCT = 1; break; } } } XFree(surfaceInfo); } } } XvFreeAdaptorInfo(info); return result; }