00001 #ifdef USING_XVMC
00002 #include "XvMCSurfaceTypes.h"
00003 #include <X11/extensions/Xv.h>
00004 #include <X11/extensions/Xvlib.h>
00005
00006 static inline Display* createXvMCDisplay()
00007 {
00008 Display *disp = MythXOpenDisplay();
00009 if (!disp)
00010 return NULL;
00011
00012 unsigned int p_version, p_release, p_request_base, p_event_base,
00013 p_error_base;
00014
00015 int ret = Success;
00016 X11S(ret = XvQueryExtension(disp, &p_version, &p_release,
00017 &p_request_base, &p_event_base,
00018 &p_error_base));
00019 if (ret != Success)
00020 {
00021 VERBOSE(VB_IMPORTANT, "XvQueryExtension failed");
00022 X11S(XCloseDisplay(disp));
00023 return 0;
00024 }
00025
00026 int mc_eventBase = 0, mc_errorBase = 0;
00027 X11S(ret = XvMCQueryExtension(disp, &mc_eventBase, &mc_errorBase));
00028 if (True != ret)
00029 {
00030 VERBOSE(VB_IMPORTANT, "XvMC extension not found");
00031 X11S(XCloseDisplay(disp));
00032 return 0;
00033 }
00034
00035 int mc_version, mc_release;
00036 X11S(ret = XvMCQueryVersion(disp, &mc_version, &mc_release));
00037 if (Success == ret)
00038 VERBOSE(VB_PLAYBACK, QString("Using XvMC version: %1.%2").
00039 arg(mc_version).arg(mc_release));
00040 return disp;
00041 }
00042
00043 int XvMCSurfaceTypes::find(int pminWidth, int pminHeight,
00044 int chroma, bool vld, bool idct, int mpeg,
00045 int pminSubpictureWidth,
00046 int pminSubpictureHeight)
00047 {
00048 if (0 == surfaces || 0 == num)
00049 return -1;
00050
00051 for (int s = 0; s < size(); s++)
00052 {
00053 if (pminWidth > maxWidth(s))
00054 continue;
00055 if (pminHeight > maxHeight(s))
00056 continue;
00057 if (chroma!=surfaces[s].chroma_format)
00058 continue;
00059 if (idct && !hasIDCTAcceleration(s))
00060 continue;
00061 if (!idct && hasIDCTAcceleration(s))
00062 continue;
00063 if (vld && !hasVLDAcceleration(s))
00064 continue;
00065 if (!vld && hasVLDAcceleration(s))
00066 continue;
00067 if (1 == mpeg && !hasMPEG1Support(s))
00068 continue;
00069 if (2 == mpeg && !hasMPEG2Support(s))
00070 continue;
00071 if (3 == mpeg && !hasH263Support(s))
00072 continue;
00073 if (4 == mpeg && !hasMPEG4Support(s))
00074 continue;
00075 if (pminSubpictureWidth > maxSubpictureWidth(s))
00076 continue;
00077 if (pminSubpictureHeight > maxSubpictureHeight(s))
00078 continue;
00079
00080 return s;
00081 }
00082
00083 return -1;
00084 }
00085
00086 void XvMCSurfaceTypes::find(int minWidth, int minHeight,
00087 int chroma, bool vld, bool idct, int mpeg,
00088 int minSubpictureWidth,
00089 int minSubpictureHeight,
00090 Display *dpy, XvPortID portMin,
00091 XvPortID portMax, XvPortID& port,
00092 int& surfNum)
00093 {
00094 VERBOSE(VB_PLAYBACK,
00095 QString("XvMCSurfaceTypes::find(w %1, h %2, chroma %3, vld %4, idct %5,"
00096 " mpeg%6, sub-width %7, sub-height %8, disp, %9")
00097 .arg(minWidth).arg(minHeight).arg(chroma)
00098 .arg(vld).arg(idct).arg(mpeg)
00099 .arg(minSubpictureWidth).arg(minSubpictureHeight)
00100 .arg(QString("p<= %9, %10 <=p, port, surfNum)")
00101 .arg(portMin).arg(portMax)));
00102
00103 port = 0;
00104 surfNum = -1;
00105 for (XvPortID p = portMin; p <= portMax; p++)
00106 {
00107 VERBOSE(VB_PLAYBACK, QString("Trying XvMC port %1").arg(p));
00108 XvMCSurfaceTypes surf(dpy, p);
00109 int s = surf.find(minWidth, minHeight, chroma, vld, idct, mpeg,
00110 minSubpictureWidth, minSubpictureHeight);
00111 if (s >= 0)
00112 {
00113 VERBOSE(VB_PLAYBACK, QString("Found a suitable XvMC surface %1")
00114 .arg(s));
00115 port = p;
00116 surfNum = s;
00117 return;
00118 }
00119 }
00120 }
00121
00122 bool XvMCSurfaceTypes::has(Display *pdisp,
00123 XvMCAccelID accel_type,
00124 uint stream_type,
00125 int chroma,
00126 uint width, uint height,
00127 uint osd_width, uint osd_height)
00128 {
00129 Display* disp = pdisp;
00130 if (!pdisp)
00131 disp = createXvMCDisplay();
00132
00133
00134
00135 XvAdaptorInfo *ai = 0;
00136 unsigned int p_num_adaptors = 0;
00137
00138 Window root = DefaultRootWindow(disp);
00139 int ret = Success;
00140 X11S(ret = XvQueryAdaptors(disp, root, &p_num_adaptors, &ai));
00141
00142 if (ret != Success)
00143 {
00144 VERBOSE(VB_IMPORTANT, "XvQueryAdaptors failed.");
00145 if (!pdisp)
00146 X11S(XCloseDisplay(disp));
00147 return false;
00148 }
00149
00150 if (!ai)
00151 {
00152 if (!pdisp)
00153 X11S(XCloseDisplay(disp));
00154 return false;
00155 }
00156
00157 for (unsigned int i = 0; i < p_num_adaptors; i++)
00158 {
00159 XvPortID p = 0;
00160 int s;
00161 if (ai[i].type == 0)
00162 continue;
00163 XvMCSurfaceTypes::find(width, height, chroma,
00164 XvVLD == accel_type, XvIDCT == accel_type,
00165 stream_type, osd_width, osd_height,
00166 disp, ai[i].base_id,
00167 ai[i].base_id + ai[i].num_ports - 1,
00168 p, s);
00169 if (0 != p)
00170 {
00171 X11L;
00172 if (p_num_adaptors > 0)
00173 XvFreeAdaptorInfo(ai);
00174 if (!pdisp)
00175 XCloseDisplay(disp);
00176 X11U;
00177 return true;
00178 }
00179 }
00180
00181 X11L;
00182 if (p_num_adaptors > 0)
00183 XvFreeAdaptorInfo(ai);
00184 if (!pdisp)
00185 XCloseDisplay(disp);
00186 X11U;
00187
00188 return false;
00189 }
00190
00191 QString XvImageFormatToString(const XvImageFormatValues &fmt)
00192 {
00193 QString id = QString("0x%1").arg(fmt.id,0,16);
00194 id = (fmt.id == GUID_IA44_PACKED) ? "IA44" : id;
00195 id = (fmt.id == GUID_AI44_PACKED) ? "AI44" : id;
00196
00197 QString type = "UNK";
00198 type = (XvRGB == fmt.type) ? "RGB" : type;
00199 type = (XvYUV == fmt.type) ? "YUV" : type;
00200
00201 QString byte_order = "UNK";
00202 byte_order = (LSBFirst == fmt.type) ? "LSB" : byte_order;
00203 byte_order = (MSBFirst == fmt.type) ? "MSB" : byte_order;
00204
00205 QString guid = "";
00206 for (uint i = 0; i < 16; i++)
00207 {
00208 guid += QString("%1%2")
00209 .arg((fmt.guid[i] / 16) & 0xf, 0, 16)
00210 .arg(fmt.guid[i] & 0xf, 0, 16);
00211 }
00212
00213 QString format = "unknown";
00214 format = (XvPacked == fmt.format) ? "packed" : format;
00215 format = (XvPlanar == fmt.format) ? "planar" : format;
00216
00217 QString addl = "";
00218 if (XvYUV == fmt.type)
00219 {
00220 addl = "\n\t\t\tYUV ";
00221 addl += QString("bits: %1,%2,%3 ").arg(fmt.y_sample_bits)
00222 .arg(fmt.u_sample_bits).arg(fmt.v_sample_bits);
00223 addl += QString("horz: %1,%2,%3 ").arg(fmt.horz_y_period)
00224 .arg(fmt.horz_u_period).arg(fmt.horz_v_period);
00225 addl += QString("vert: %1,%2,%3 ").arg(fmt.vert_y_period)
00226 .arg(fmt.vert_u_period).arg(fmt.vert_v_period);
00227
00228 QString slo = "unknown";
00229 slo = (fmt.scanline_order == XvTopToBottom) ? "top->bot" : slo;
00230 slo = (fmt.scanline_order == XvBottomToTop) ? "bot->top" : slo;
00231
00232 addl += QString("scan order: %1").arg(slo);
00233
00234
00235 }
00236
00237 return QString("id: %1 type: %2 order: %3 fmt: %4 bbp: %5"
00238 "%7")
00239
00240 .arg(id).arg(type).arg(byte_order).arg(format)
00241 .arg(fmt.bits_per_pixel)
00242
00243 .arg(addl);
00244 }
00245
00246
00247 QString XvMCSurfaceTypes::toString(Display *pdisp, XvPortID p) const
00248 {
00249 ostringstream os;
00250 for (int j = 0; j < size(); j++)
00251 {
00252 QString chroma = "unknown";
00253 chroma = hasChroma420(j) ? "420" : chroma;
00254 chroma = hasChroma422(j) ? "422" : chroma;
00255 chroma = hasChroma444(j) ? "444" : chroma;
00256
00257 QString accel = "";
00258 accel += hasMotionCompensationAcceleration(j)?"MC, " : "";
00259 accel += hasIDCTAcceleration(j) ? "IDCT, " : "";
00260 accel += hasVLDAcceleration(j) ? "VLD, " : "";
00261 accel += hasMPEG1Support(j) ? "MPEG1, " : "";
00262 accel += hasMPEG2Support(j) ? "MPEG2, " : "";
00263 accel += hasMPEG4Support(j) ? "MPEG4-1, " : "";
00264 accel += hasH263Support(j) ? "MPEG1-AVC, " : "";
00265
00266 bool backend = hasBackendSubpicture(j);
00267 bool overlay = hasOverlay(j);
00268 bool indep = hasSubpictureScaling(j);
00269 bool intrau = isIntraUnsigned(j);
00270 bool copytop = hasCopyToPBuffer(j);
00271 QString flags = QString("0x%1 ")
00272 .arg(surfaces[j].flags,0,16);
00273 flags += (backend) ? "backend" : "blend";
00274 flags += (overlay) ? ", overlay" : "";
00275 flags += (indep) ? ", independent_scaling" : "";
00276 flags += (intrau) ? ", intra_unsigned" : ", intra_signed";
00277 flags += (copytop) ? ", copy_to_pbuf" : "";
00278
00279 os<<"\t\t"
00280 <<QString("type_id: 0x%1").arg(surfaceTypeID(j))
00281 <<" chroma: "<<chroma
00282 <<" max_size: "
00283 <<maxWidth(j)<<"x"<<maxHeight(j)
00284 <<" sub_max_size: "
00285 <<maxSubpictureWidth(j)<<"x"
00286 <<maxSubpictureHeight(j)
00287 <<endl<<"\t\t"
00288 <<"accel: "<<accel<<" flags: "<<flags<<endl;
00289
00290 if (pdisp && p)
00291 {
00292 int num = 0;
00293 XvImageFormatValues *xvfmv = NULL;
00294 X11S(xvfmv = XvMCListSubpictureTypes(pdisp, p,
00295 surfaceTypeID(j),
00296 &num));
00297 for (int k = (xvfmv) ? 0 : num; k < num; k++)
00298 os<<"\t\t\t"<<XvImageFormatToString(xvfmv[k])<<endl;
00299
00300 if (xvfmv)
00301 X11S(XFree(xvfmv));
00302 }
00303 }
00304 if (size())
00305 os<<endl;
00306
00307 return QString(os.str().c_str());
00308 }
00309
00310 QString XvMCSurfaceTypes::XvMCDescription(Display *pdisp)
00311 {
00312 Display* disp = pdisp;
00313 if (!pdisp)
00314 disp = createXvMCDisplay();
00315
00316 XvAdaptorInfo *ai = 0;
00317 unsigned int p_num_adaptors = 0;
00318
00319 Window root = DefaultRootWindow(disp);
00320 int ret = Success;
00321 X11S(ret = XvQueryAdaptors(disp, root, &p_num_adaptors, &ai));
00322
00323 if (ret != Success)
00324 {
00325 if (!pdisp)
00326 X11S(XCloseDisplay(disp));
00327 return "XvQueryAdaptors failed.";
00328 }
00329
00330 if (!ai)
00331 {
00332 if (!pdisp)
00333 X11S(XCloseDisplay(disp));
00334 return "No XVideo Capable Adaptors.";
00335 }
00336
00337 ostringstream os;
00338 for (uint i = 0; i < p_num_adaptors; i++)
00339 {
00340 QString type = "";
00341 type += (ai[i].type & XvInputMask) ? "input, " : "";
00342 type += (ai[i].type & XvOutputMask) ? "output, " : "";
00343 type += (ai[i].type & XvImageMask) ? "image, " : "";
00344
00345 os<<QString("Adaptor #%1 ").arg(i) +
00346 QString("name: %1 base_id: %2 num_ports: %3 type: %4"
00347 "num_fmt: %5")
00348 .arg(ai[i].name).arg(ai[i].base_id)
00349 .arg(ai[i].num_ports).arg(type)
00350 .arg(ai[i].num_formats)<<endl;
00351
00352 for (uint j = 0; j < ai[i].num_formats; j++)
00353 {
00354 XvFormat &fmt = ai[i].formats[j];
00355 os<<QString("\tFormat #%1 ").arg(j,2)
00356 <<QString("depth: %1 ").arg((int)fmt.depth,2)
00357 <<QString("visual id: 0x%1").arg(fmt.visual_id,0,16)<<endl;
00358 }
00359 os<<endl;
00360
00361 XvPortID portMin = ai[i].base_id;
00362 XvPortID portMax = ai[i].base_id + ai[i].num_ports - 1;
00363 for (XvPortID p = portMin; p <= portMax; p++)
00364 {
00365 XvMCSurfaceTypes surf(pdisp, p);
00366 os<<"\tPort #"<<p<<" size: "<<surf.size()<<endl;
00367 os<<surf.toString(pdisp, p);
00368 }
00369 os<<endl<<endl;
00370 }
00371
00372 X11L;
00373 if (p_num_adaptors > 0)
00374 XvFreeAdaptorInfo(ai);
00375 if (!pdisp)
00376 XCloseDisplay(disp);
00377 X11U;
00378
00379 return QString(os.str().c_str());
00380 }
00381
00382 #endif // USING_XVMC