z4l.c revision f29dbc25
1/* 2 * Copyright (c) 2006 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 * 22 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23 * contributors may be used to endorse or promote products derived from this 24 * software without specific prior written permission. 25 */ 26 27/* prototype Xv interface for lxv4l2 driver */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include <sys/time.h> 34#include <sys/fcntl.h> 35#include <sys/mman.h> 36#include <sys/ioctl.h> 37#include <errno.h> 38#include <unistd.h> 39#include <string.h> 40#include <ctype.h> 41#include <stdlib.h> 42 43#include "xf86.h" 44#include <X11/extensions/Xv.h> 45#include "xf86_OSproc.h" 46#include "compiler.h" 47#include "xf86xv.h" 48#include "fourcc.h" 49 50#include <linux/types.h> 51 52#define __s64 __s_64 53typedef long long __s64; 54 55#define __u64 __u_64 56typedef unsigned long long __u64; 57 58#include "linux/videodev.h" 59#define __user 60#include "linux/videodev2.h" 61 62typedef signed long long s64; 63typedef unsigned long long u64; 64 65int debuglvl = 0; 66 67#define NONBLK_IO 68#undef HAVE_SELECT 69 70#define DEBUG 1 71#ifdef DEBUG 72#define DBLOG(n,s...) do { \ 73 if ( debuglvl >= (n) ) \ 74 xf86Msg(X_INFO, "z4l: " s); \ 75 } while(0) 76#else 77#define DBLOG(n,s...) do {} while(0) 78#endif 79 80#define DEFAULT_COLORKEY 0x010203 81#define DEFAULT_KEYMODE 0 82 83#define MAX_BUFFERS 4 84#define MAX_OVLY_WIDTH 2048 85#define MAX_OVLY_HEIGHT 2048 86 87static char *z4l_dev_paths[] = { 88 "/dev/videox", NULL 89}; 90 91#define ATTR_ENCODING "encoding" 92#define ATTR_ENCODING_ID -1 93#define ATTR_KEYMODE "keymode" 94#define ATTR_KEYMODE_ID -2 95#define ATTR_COLORKEY "colorkey" 96#define ATTR_COLORKEY_ID -3 97#define ATTR_MAX_ID 3 98 99#ifdef XvExtension 100 101static XF86VideoFormatRec Formats[] = { 102 {8, PseudoColor}, 103 {15, TrueColor}, 104 {16, TrueColor}, 105 {24, TrueColor} 106}; 107 108#define NUM_FORMATS (sizeof(Formats)/sizeof(Formats[0])) 109 110#define FOURCC_Y800 0x30303859 111#define XVIMAGE_Y800 \ 112 { \ 113 FOURCC_Y800, \ 114 XvYUV, \ 115 LSBFirst, \ 116 {'Y','8','0','0', \ 117 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ 118 8, \ 119 XvPacked, \ 120 1, \ 121 0, 0, 0, 0, \ 122 8, 0, 0, \ 123 1, 0, 0, \ 124 1, 0, 0, \ 125 {'Y','8','0','0', \ 126 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ 127 XvTopToBottom \ 128 } 129 130static XF86ImageRec pixfmts[] = { 131 XVIMAGE_UYVY, XVIMAGE_YUY2, 132 XVIMAGE_I420, XVIMAGE_YV12, 133 XVIMAGE_Y800, 134}; 135 136#define NUM_PIXFMTS (sizeof(pixfmts)/sizeof(pixfmts[0])) 137 138typedef struct s_std_data 139{ 140 int inp; 141 v4l2_std_id std; 142 unsigned int fmt; 143} t_std_data; 144 145typedef struct s_ovly_bfrs 146{ 147 void *start; 148 unsigned long offset; 149 size_t length; 150} t_ovly_bfrs; 151 152typedef struct 153{ 154 int fd; 155 int run; 156 int dir; 157 int nbfrs; 158 int bufno; 159 int bufsz; 160 int last; 161 int width, height; 162 int keymode, colorkey; 163 int src_is_set, src_x, src_y, src_w, src_h; 164 int drw_is_set, drw_x, drw_y, drw_w, drw_h; 165 unsigned int pixfmt; 166 char dev_path[32]; 167 t_ovly_bfrs bfrs[MAX_BUFFERS]; 168 XF86VideoAdaptorPtr adpt; 169 XF86VideoEncodingPtr enc; 170 RegionRec clips; 171 int attrIds[1]; 172} Z4lPortPrivRec; 173 174static int z4l_x_offset = 0; 175static int z4l_y_offset = 0; 176static int Z4l_nAdaptors = 0; 177static XF86VideoAdaptorPtr *Z4l_pAdaptors = NULL; 178 179static int 180IoCtl(int fd, unsigned int fn, void *arg, int flag) 181{ 182 int ret; 183 184 errno = 0; 185 ret = ioctl(fd, fn, arg); 186 if (ret != 0 && flag != 0) 187 DBLOG(0, "ioctl(%08x)=%d\n", fn, ret); 188 return ret; 189} 190 191static void 192z4l_ovly_unmap(Z4lPortPrivRec * pPriv) 193{ 194#ifdef LINUX_2_6 195 int i, nbfrs; 196 197 nbfrs = pPriv->nbfrs; 198 for (i = 0; i < nbfrs; ++i) { 199 if (pPriv->bfrs[i].start != NULL) { 200 munmap(pPriv->bfrs[i].start, pPriv->bfrs[i].length); 201 pPriv->bfrs[i].start = NULL; 202 } 203 } 204#else 205 if (pPriv->bfrs[0].start != NULL) { 206 munmap((void *)pPriv->bfrs[0].start, pPriv->bufsz); 207 pPriv->bfrs[0].start = NULL; 208 } 209#endif 210 pPriv->nbfrs = -1; 211 pPriv->bufsz = -1; 212 pPriv->last = -1; 213} 214 215static void 216z4l_ovly_map(Z4lPortPrivRec * pPriv, int dir) 217{ 218 long offset, bsz; 219 int i, fd; 220 struct v4l2_buffer bfr; 221 struct v4l2_requestbuffers req; 222 int type = dir >= 0 ? 223 V4L2_BUF_TYPE_VIDEO_CAPTURE : V4L2_BUF_TYPE_VIDEO_OVERLAY; 224 if (pPriv->run > 0) { 225 DBLOG(1, "busy\n"); 226 return; 227 } 228 fd = pPriv->fd; 229 memset(&req, 0, sizeof(req)); 230 req.type = type; 231 req.memory = V4L2_MEMORY_MMAP; 232 req.count = MAX_BUFFERS; 233 if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) 234 goto xit; 235 pPriv->nbfrs = req.count; 236 if (pPriv->nbfrs <= 0) { 237 DBLOG(1, "no vidmem\n"); 238 return; 239 } 240 memset(&pPriv->bfrs, 0, sizeof(pPriv->bfrs)); 241 242 for (i = 0; i < pPriv->nbfrs; ++i) { 243 memset(&bfr, 0, sizeof(bfr)); 244 bfr.type = type; 245 bfr.index = i; 246 if (ioctl(fd, VIDIOC_QUERYBUF, &bfr) < 0) 247 goto xit; 248 offset = bfr.m.offset; 249 pPriv->bfrs[i].offset = offset; 250 pPriv->bfrs[i].length = bfr.length; 251 bsz = offset + bfr.length; 252 if (pPriv->bufsz < bsz) 253 pPriv->bufsz = bsz; 254 } 255 256#ifdef LINUX_2_6 257 for (i = 0; i < pPriv->nbfrs; ++i) { 258 pPriv->bfrs[i].start = mmap(NULL, bfr.length, PROT_READ | PROT_WRITE, 259 MAP_SHARED, fd, pPriv->bfrs[i].offset); 260 if (pPriv->bfrs[i].start == MAP_FAILED) 261 goto xit; 262 } 263#else 264 pPriv->bfrs[0].offset = 0; 265 pPriv->bfrs[0].start = 266 mmap(NULL, pPriv->bufsz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 267 268 if (pPriv->bfrs[0].start == MAP_FAILED) { 269 pPriv->bfrs[0].start = NULL; 270 goto xit; 271 } 272 273 offset = (unsigned long)pPriv->bfrs[0].start; 274 for (i = 1; i < pPriv->nbfrs; ++i) 275 pPriv->bfrs[i].start = (void *)(offset + pPriv->bfrs[i].offset); 276#endif 277 278 for (i = 0; i < pPriv->nbfrs; ++i) { 279 DBLOG(3, "bfr %d ofs %#lx adr %p sz %lu\n", i, pPriv->bfrs[i].offset, 280 pPriv->bfrs[i].start, (unsigned long)pPriv->bfrs[i].length); 281 memset(pPriv->bfrs[i].start, 0x80, pPriv->bfrs[i].length); 282 } 283 284 pPriv->last = 0; 285 while (pPriv->last < pPriv->nbfrs - 1) { 286 bfr.index = pPriv->last++; 287 bfr.type = type; 288 if (ioctl(fd, VIDIOC_QBUF, &bfr) < 0) 289 goto xit; 290 } 291 return; 292 293 xit: 294 z4l_ovly_unmap(pPriv); 295} 296 297static int 298z4l_ovly_dqbuf(Z4lPortPrivRec * pPriv) 299{ 300 int stat; 301 struct v4l2_buffer bfr; 302 int fd = pPriv->fd; 303 304#ifdef HAVE_SELECT 305 struct timeval tmo; 306 fd_set dqset; 307 308 FD_ZERO(&dqset); 309 FD_SET(pPriv->fd, &dqset); 310 tmo.tv_sec = 0; 311 tmo.tv_usec = 0; 312 if (select(fd + 1, &dqset, NULL, NULL, &tmo) <= 0) 313 return -1; 314#endif 315 memset(&bfr, 0, sizeof(bfr)); 316 bfr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 317 stat = ioctl(fd, VIDIOC_DQBUF, &bfr); 318 DBLOG(3, "dqbuf %d,%d,%d,%d\n", stat, bfr.index, pPriv->last, errno); 319 320 return stat == 0 ? bfr.index : -1; 321} 322 323static int 324z4l_open_device(Z4lPortPrivRec * pPriv) 325{ 326 int enable; 327 328 if (pPriv->fd < 0) { 329 pPriv->fd = open(&pPriv->dev_path[0], O_RDWR, 0); 330 DBLOG(1, "open(%s)=%d\n", &pPriv->dev_path[0], pPriv->fd); 331 enable = 1; 332#ifdef NONBLK_IO 333 if (IoCtl(pPriv->fd, FIONBIO, &enable, 1) != 0) { 334 DBLOG(1, "open cant enable nonblocking\n"); 335 close(pPriv->fd); 336 pPriv->fd = -1; 337 } 338#endif 339 } 340 return pPriv->fd; 341} 342 343static int 344z4l_close_device(Z4lPortPrivRec * pPriv) 345{ 346 int ret = 0; 347 348 if (pPriv->fd >= 0) { 349 ret = close(pPriv->fd); 350 pPriv->fd = -1; 351 DBLOG(1, "close()=%d\n", ret); 352 } 353 if (pPriv->run > 0) { 354 z4l_ovly_unmap(pPriv); 355 pPriv->run = -1; 356 } 357 358 return ret; 359} 360 361static int 362z4l_ovly_reset(Z4lPortPrivRec * pPriv) 363{ 364 int ret = 0; 365 366 if (pPriv->run > 0) { 367 z4l_close_device(pPriv); 368 ret = z4l_open_device(pPriv); 369 } 370 371 return ret; 372} 373 374static unsigned int 375z4l_fourcc_pixfmt(int fourcc) 376{ 377 unsigned int pixfmt = -1; 378 379 switch (fourcc) { 380 case FOURCC_UYVY: 381 pixfmt = V4L2_PIX_FMT_UYVY; 382 break; 383 case FOURCC_YV12: 384 pixfmt = V4L2_PIX_FMT_YVU420; 385 break; 386 case FOURCC_Y800: 387 case FOURCC_I420: 388 pixfmt = V4L2_PIX_FMT_YUV420; 389 break; 390 case FOURCC_YUY2: 391 pixfmt = V4L2_PIX_FMT_YUYV; 392 break; 393 } 394 395 return pixfmt; 396} 397static void 398z4l_ovly_pixfmt(Z4lPortPrivRec * pPriv, unsigned int pixfmt) 399{ 400 struct v4l2_framebuffer fbuf; 401 402 DBLOG(1, "pixfmt %4.4s %4.4s\n", (char *)&pPriv->pixfmt, (char *)&pixfmt); 403 memset(&fbuf, 0, sizeof(fbuf)); 404 IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1); 405 fbuf.fmt.pixelformat = pixfmt; 406 fbuf.base = NULL; 407 IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1); 408 pPriv->pixfmt = pixfmt; 409} 410 411static void 412z4l_ovly_bfr(Z4lPortPrivRec * pPriv, int width, int height) 413{ 414 struct v4l2_format fmt; 415 416 DBLOG(1, "sfmt ovly %dx%d\n", width, height); 417 memset(&fmt, 0, sizeof(fmt)); 418 fmt.type = 0x102; 419 IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); 420 fmt.fmt.win.field = V4L2_FIELD_NONE; 421 fmt.fmt.win.w.width = pPriv->width = width; 422 fmt.fmt.win.w.height = pPriv->height = height; 423 IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); 424} 425 426static void 427z4l_ovly_rect(Z4lPortPrivRec * pPriv, 428 int src_x, int src_y, int src_w, int src_h, 429 int drw_x, int drw_y, int drw_w, int drw_h) 430{ 431 int x, dx, w, y, dy, h; 432 struct v4l2_format fmt; 433 434 pPriv->src_x = src_x; 435 pPriv->src_y = src_y; 436 pPriv->src_w = src_w; 437 pPriv->src_h = src_h; 438 pPriv->drw_x = drw_x; 439 pPriv->drw_y = drw_y; 440 pPriv->drw_w = drw_w; 441 pPriv->drw_h = drw_h; 442 443 if ((drw_x -= z4l_x_offset) < 0) { 444 if ((w = pPriv->drw_w) <= 0) 445 w = 1; 446 x = -drw_x; 447 dx = x * pPriv->src_w / w; 448 src_x = pPriv->src_x + dx; 449 src_w = pPriv->src_w - dx; 450 drw_w = pPriv->drw_w - x; 451 drw_x = 0; 452 } 453 454 if ((drw_y -= z4l_y_offset) < 0) { 455 if ((h = pPriv->drw_h) <= 0) 456 h = 1; 457 y = -drw_y; 458 dy = y * pPriv->src_h / h; 459 src_y = pPriv->src_y + dy; 460 src_h = pPriv->src_h - dy; 461 drw_h = pPriv->drw_h - y; 462 drw_y = 0; 463 } 464 465 memset(&fmt, 0, sizeof(fmt)); 466 fmt.type = 0x100; 467 IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); 468 if (pPriv->src_is_set != 0) { 469 if (src_x != fmt.fmt.win.w.left || src_y != fmt.fmt.win.w.top || 470 src_w != fmt.fmt.win.w.width || src_h != fmt.fmt.win.w.height) 471 pPriv->src_is_set = 0; 472 } 473 if (pPriv->src_is_set == 0) { 474 pPriv->src_is_set = 1; 475 fmt.fmt.win.w.left = src_x; 476 fmt.fmt.win.w.top = src_y; 477 fmt.fmt.win.w.width = src_w; 478 fmt.fmt.win.w.height = src_h; 479 IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); 480 DBLOG(3, " set src %d,%d %dx%d\n", src_x, src_y, src_w, src_h); 481 } 482 memset(&fmt, 0, sizeof(fmt)); 483 fmt.type = 0x101; 484 IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1); 485 if (pPriv->drw_is_set != 0) { 486 if (drw_x != fmt.fmt.win.w.left || drw_y != fmt.fmt.win.w.top || 487 drw_w != fmt.fmt.win.w.width || drw_h != fmt.fmt.win.w.height) 488 pPriv->drw_is_set = 0; 489 } 490 if (pPriv->drw_is_set == 0) { 491 pPriv->drw_is_set = 1; 492 fmt.fmt.win.w.left = drw_x; 493 fmt.fmt.win.w.top = drw_y; 494 fmt.fmt.win.w.width = drw_w; 495 fmt.fmt.win.w.height = drw_h; 496 IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1); 497 DBLOG(3, " set drw %d,%d %dx%d\n", drw_x, drw_y, drw_w, drw_h); 498 } 499} 500 501static void 502z4l_ovly_pitch(unsigned int pixfmt, int w, int h, int *py_pitch, 503 int *puv_pitch, int *poffset1, int *poffset2, int *psize) 504{ 505 int y_pitch, uv_pitch; 506 int offset1, offset2; 507 int size, is_420; 508 509 switch (pixfmt) { 510 case V4L2_PIX_FMT_YVU420: 511 case V4L2_PIX_FMT_YUV420: 512 is_420 = 1; 513 y_pitch = ((w + 1) / 2) * 2; 514 uv_pitch = (w + 1) / 2; 515 break; 516 default: 517 is_420 = 0; 518 y_pitch = ((w + 1) / 2) * 4; 519 uv_pitch = 0; 520 break; 521 } 522 523 offset1 = y_pitch * h; 524 offset2 = uv_pitch * h; 525 526 if (is_420 != 0) 527 offset2 /= 2; 528 529 size = offset1 + 2 * offset2; 530 *py_pitch = y_pitch; 531 *puv_pitch = uv_pitch; 532 *poffset1 = offset1; 533 *poffset2 = offset2; 534 *psize = size; 535} 536 537static int 538z4l_ovly_set_colorkey(Z4lPortPrivRec * pPriv, int key) 539{ 540 struct v4l2_format fmt; 541 542 memset(&fmt, 0, sizeof(fmt)); 543 fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 544 if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) 545 return 0; 546 fmt.fmt.win.chromakey = key; 547 if (IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1) < 0) 548 return 0; 549 pPriv->colorkey = key; 550 551 return 1; 552} 553 554static int 555z4l_ovly_get_colorkey(Z4lPortPrivRec * pPriv, int *key) 556{ 557 struct v4l2_format fmt; 558 559 memset(&fmt, 0, sizeof(fmt)); 560 fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 561 if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) 562 return 0; 563 *key = fmt.fmt.win.chromakey; 564 565 return 1; 566} 567 568static int 569z4l_ovly_set_keymode(Z4lPortPrivRec * pPriv, int enable) 570{ 571 struct v4l2_framebuffer fbuf; 572 573 memset(&fbuf, 0, sizeof(fbuf)); 574 if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) 575 return 0; 576 577 if (enable != 0) 578 fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; 579 else 580 fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; 581 582 fbuf.base = NULL; 583 if (IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1) < 0) 584 return 0; 585 pPriv->keymode = enable; 586 587 return 1; 588} 589 590static int 591z4l_ovly_get_keymode(Z4lPortPrivRec * pPriv, int *enable) 592{ 593 struct v4l2_framebuffer fbuf; 594 595 memset(&fbuf, 0, sizeof(fbuf)); 596 if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) 597 return 0; 598 *enable = (fbuf.flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0 ? 1 : 0; 599 600 return 1; 601} 602 603static int 604z4l_ovly_set_encoding(Z4lPortPrivRec * pPriv, int id) 605{ 606 int l, n, inp; 607 char *cp; 608 t_std_data *sp; 609 XF86VideoEncodingPtr enc; 610 XF86VideoAdaptorPtr adpt; 611 v4l2_std_id std; 612 struct v4l2_format fmt; 613 struct v4l2_framebuffer fbuf; 614 615 adpt = pPriv->adpt; 616 DBLOG(1, "z4l_ovly_set_encoding(%d)\n", id); 617 if (id < 0 || id >= adpt->nEncodings) 618 return 0; 619 enc = &adpt->pEncodings[id]; 620 cp = &enc->name[0]; 621 n = sizeof(int) - 1; 622 l = strlen(cp) + 1; 623 l = (l + n) & ~n; 624 sp = (t_std_data *) (cp + l); 625 inp = sp->inp; 626 627 DBLOG(1, " nm %s fmt %4.4s inp %d std %llx\n", 628 cp, (char *)&sp->fmt, sp->inp, sp->std); 629 630 if (IoCtl(pPriv->fd, VIDIOC_S_INPUT, &inp, 1) < 0) 631 return 0; 632 633 std = sp->std; 634 if (IoCtl(pPriv->fd, VIDIOC_S_STD, &std, 1) < 0) 635 return 0; 636 637 memset(&fmt, 0, sizeof(fmt)); 638 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 639 if (IoCtl(pPriv->fd, VIDIOC_G_FMT, &fmt, 1) < 0) 640 return 0; 641 642 fmt.fmt.pix.pixelformat = sp->fmt; 643 if (IoCtl(pPriv->fd, VIDIOC_S_FMT, &fmt, 1) < 0) 644 return 0; 645 memset(&fbuf, 0, sizeof(fbuf)); 646 647 if (IoCtl(pPriv->fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) 648 return 0; 649 650 fbuf.fmt.pixelformat = sp->fmt; 651 fbuf.base = NULL; 652 if (IoCtl(pPriv->fd, VIDIOC_S_FBUF, &fbuf, 1) < 0) 653 return 0; 654 pPriv->pixfmt = sp->fmt; 655 pPriv->enc = enc; 656 pPriv->src_is_set = pPriv->drw_is_set = 0; 657 658 return 1; 659} 660 661static int 662z4l_ovly_get_encoding(Z4lPortPrivRec * pPriv, int *id) 663{ 664 XF86VideoEncodingPtr enc = pPriv->enc; 665 666 *id = enc->id; 667 return 1; 668} 669 670static void 671z4l_ovly_stop(Z4lPortPrivRec * pPriv) 672{ 673 int type, enable, fd; 674 675 if (pPriv->run < 0) 676 return; 677 678 fd = pPriv->fd; 679 if (pPriv->dir > 0) { 680 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 681 ioctl(fd, VIDIOC_STREAMOFF, &type); 682 } 683 684 if (pPriv->dir <= 0) { 685 enable = 0; 686 ioctl(fd, VIDIOC_OVERLAY, &enable); 687 } 688 689 if (pPriv->dir != 0) 690 z4l_ovly_unmap(pPriv); 691 692 pPriv->run = -1; 693 z4l_close_device(pPriv); 694} 695 696static void 697z4l_ovly_start(Z4lPortPrivRec * pPriv, int dir) 698{ 699 int enable; 700 701 if (pPriv->run >= 0) 702 return; 703 704 if ((pPriv->dir = dir) != 0) 705 z4l_ovly_map(pPriv, dir); 706 707 enable = 1; 708 709 if (IoCtl(pPriv->fd, VIDIOC_OVERLAY, &enable, 1) != 0) { 710 z4l_ovly_stop(pPriv); 711 return; 712 } 713 714 pPriv->run = 1; 715} 716 717static int 718z4l_region_equal(RegionPtr ap, RegionPtr bp) 719{ 720 int nboxes; 721 BoxPtr abox, bbox; 722 723 if (ap == NULL && bp == NULL) 724 return 1; 725 if (ap == NULL || bp == NULL) 726 return 0; 727 728 if ((nboxes = REGION_NUM_RECTS(ap)) != REGION_NUM_RECTS(bp) || 729 ap->extents.x1 != bp->extents.x1 || 730 ap->extents.x2 != bp->extents.x2 731 || ap->extents.y1 != bp->extents.y1 732 || ap->extents.y2 != bp->extents.y2) 733 return 0; 734 735 abox = REGION_RECTS(ap); 736 bbox = REGION_RECTS(bp); 737 738 while (--nboxes >= 0) { 739 if (abox->x1 != bbox->x1 || abox->y1 != bbox->y1 || 740 abox->x2 != bbox->x2 || abox->y2 != bbox->y2) 741 return 0; 742 ++abox; 743 ++bbox; 744 } 745 746 return 1; 747} 748 749static void 750z4l_setup_colorkey(Z4lPortPrivRec * pPriv, ScreenPtr pScrn, 751 RegionPtr clipBoxes) 752{ 753 if (pPriv->run > 0 && pPriv->dir <= 0 && pPriv->keymode != 0 && 754 z4l_region_equal(&pPriv->clips, clipBoxes) == 0) { 755 xf86XVFillKeyHelper(pScrn, pPriv->colorkey, clipBoxes); 756 REGION_COPY(pScrn, &pPriv->clips, clipBoxes); 757 } 758} 759 760static void 761Z4lStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) 762{ 763 Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 764 765 DBLOG(1, "Z4lStopVideo()\n"); 766 767 if (exit != 0) 768 z4l_ovly_stop(pPriv); 769 else 770 pPriv->src_is_set = pPriv->drw_is_set = 0; 771 772 REGION_EMPTY(pScrni->pScreen, &pPriv->clips); 773} 774 775static void 776Z4lQueryBestSize(ScrnInfoPtr pScrni, Bool motion, 777 short vid_w, short vid_h, short drw_w, short drw_h, 778 unsigned int *p_w, unsigned int *p_h, pointer data) 779{ 780 if (drw_w > MAX_OVLY_WIDTH) 781 drw_w = MAX_OVLY_WIDTH; 782 if (drw_h > MAX_OVLY_HEIGHT) 783 drw_h = MAX_OVLY_HEIGHT; 784 785 *p_w = drw_w; 786 *p_h = drw_h; 787 DBLOG(1, "Z4lQueryBestSize(%d, src %dx%d dst %dx%d)\n", motion, vid_w, 788 vid_h, drw_w, drw_h); 789} 790 791static int 792Z4lPutImage(ScrnInfoPtr pScrni, short src_x, short src_y, short drw_x, 793 short drw_y, short src_w, short src_h, short drw_w, short drw_h, 794 int id, unsigned char *buf, short width, short height, 795 Bool sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 796{ 797 int fd, size; 798 int y_pitch, uv_pitch, offset1, offset2; 799 unsigned char *src, *dst; 800 unsigned int pixfmt; 801 struct v4l2_buffer bfr; 802 Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 803 804 if (pPriv->run > 0 && pPriv->dir >= 0) 805 return BadMatch; 806 if (pPriv->fd < 0) { 807 z4l_open_device(pPriv); 808 if (pPriv->fd < 0) 809 return BadValue; 810 } 811 812 fd = pPriv->fd; 813 if (pPriv->run < 0) { 814 DBLOG(2, "PutImg id %#x src %d,%d %dx%d drw %d,%d %dx%d bfr %p " 815 "%dx%d data %p\n", id, src_x, src_y, src_w, src_h, drw_x, 816 drw_y, drw_w, drw_h, buf, width, height, data); 817 pPriv->pixfmt = pPriv->height = -1; 818 pPriv->src_is_set = pPriv->drw_is_set = 0; 819 } 820 821 pixfmt = z4l_fourcc_pixfmt(id); 822 if (pixfmt != pPriv->pixfmt) { 823 z4l_ovly_reset(pPriv); 824 z4l_ovly_pixfmt(pPriv, pixfmt); 825 } 826 if (pPriv->width != width || pPriv->height != height) { 827 z4l_ovly_reset(pPriv); 828 z4l_ovly_bfr(pPriv, width, height); 829 } 830 831 if (pPriv->src_is_set == 0 || pPriv->drw_is_set == 0 || 832 pPriv->src_x != src_x || pPriv->src_y != src_y || 833 pPriv->src_w != src_w || pPriv->src_h != src_h || 834 pPriv->drw_x != drw_x || pPriv->drw_y != drw_y || 835 pPriv->drw_w != drw_w || pPriv->drw_h != drw_h) 836 z4l_ovly_rect(pPriv, src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, 837 drw_h); 838 839 if (pPriv->run < 0) { 840 z4l_ovly_start(pPriv, -1); 841 if (pPriv->run < 0) 842 return BadValue; 843 } 844 845 if (pPriv->last < 0 && (pPriv->last = z4l_ovly_dqbuf(pPriv)) < 0) 846 return BadAlloc; 847 848 z4l_ovly_pitch(pixfmt, width, height, &y_pitch, &uv_pitch, 849 &offset1, &offset2, &size); 850 src = buf; 851 dst = (unsigned char *)pPriv->bfrs[pPriv->last].start; 852 DBLOG(3, "cpy %4.4s src %p dst %p yp %d uvp %d o1 %d o2 %d sz %d\n", 853 (char *)&id, src, dst, y_pitch, uv_pitch, offset1, offset2, size); 854 855 if (id == FOURCC_Y800) { 856 memcpy(dst, src, offset1); 857 src += offset1; 858 dst += offset1; 859 memset(dst, 0x80, 2 * offset2); 860 } else 861 memcpy(dst, src, size); 862 863 memset(&bfr, 0, sizeof(bfr)); 864 bfr.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 865 bfr.index = pPriv->last; 866 bfr.timestamp.tv_sec = 0; 867 bfr.timestamp.tv_usec = 0; 868 bfr.flags |= V4L2_BUF_FLAG_TIMECODE; 869 if (IoCtl(fd, VIDIOC_QBUF, &bfr, 1) != 0) 870 return BadAccess; 871 872 pPriv->last = z4l_ovly_dqbuf(pPriv); 873 z4l_setup_colorkey(pPriv, pScrni->pScreen, clipBoxes); 874 875 return Success; 876} 877 878static int 879Z4lQueryImageAttributes(ScrnInfoPtr pScrni, int id, unsigned short *width, 880 unsigned short *height, int *pitches, int *offsets) 881{ 882 int w, h, size; 883 int y_pitch, uv_pitch, offset1, offset2; 884 unsigned int pixfmt = z4l_fourcc_pixfmt(id); 885 886 w = *width; 887 h = *height; 888 if (w > MAX_OVLY_WIDTH) 889 w = MAX_OVLY_WIDTH; 890 if (h > MAX_OVLY_HEIGHT) 891 h = MAX_OVLY_HEIGHT; 892 893 z4l_ovly_pitch(pixfmt, w, h, &y_pitch, &uv_pitch, 894 &offset1, &offset2, &size); 895 896 if (offsets != NULL) 897 offsets[0] = 0; 898 if (pitches != NULL) 899 pitches[0] = y_pitch; 900 901 switch (pixfmt) { 902 case V4L2_PIX_FMT_YVU420: 903 case V4L2_PIX_FMT_YUV420: 904 if (offsets != NULL) { 905 offsets[1] = offset1; 906 offsets[2] = offset1 + offset2; 907 } 908 if (pitches != NULL) 909 pitches[1] = pitches[2] = uv_pitch; 910 h = (h + 1) & ~1; 911 break; 912 } 913 914 w = (w + 1) & ~1; 915 *width = w; 916 *height = h; 917 DBLOG(1, "Z4lQueryImageAttributes(%4.4s) = %d, %dx%d %d/%d %d/%d\n", 918 (char *)&id, size, w, h, y_pitch, uv_pitch, offset1, offset2); 919 920 return size; 921} 922 923static int 924Z4lPutVideo(ScrnInfoPtr pScrni, short src_x, short src_y, short drw_x, 925 short drw_y, short src_w, short src_h, short drw_w, short drw_h, 926 RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 927{ 928 int id; 929 Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 930 931 DBLOG(2, "PutVid src %d,%d %dx%d drw %d,%d %dx%d data %p\n", 932 src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, data); 933 934 if (z4l_open_device(pPriv) >= 0) { 935 if (pPriv->run < 0) { 936 DBLOG(2, "PutVid start\n"); 937 z4l_ovly_get_encoding(pPriv, &id); 938 z4l_ovly_set_encoding(pPriv, id); 939 } 940 DBLOG(2, "PutVid priv %d,%d %dx%d drw %d,%d %dx%d\n", 941 pPriv->src_x, pPriv->src_y, pPriv->src_w, pPriv->src_h, 942 pPriv->drw_x, pPriv->drw_y, pPriv->drw_w, pPriv->drw_h); 943 if (pPriv->src_is_set == 0 || pPriv->drw_is_set == 0 || 944 pPriv->src_w != src_w || pPriv->src_h != src_h || 945 pPriv->drw_x != drw_x || pPriv->drw_y != drw_y || 946 pPriv->drw_w != drw_w || pPriv->drw_h != drw_h) 947 z4l_ovly_rect(pPriv, src_x, src_y, src_w, src_h, drw_x, drw_y, 948 drw_w, drw_h); 949 if (pPriv->run < 0) 950 z4l_ovly_start(pPriv, 0); 951 952 z4l_setup_colorkey(pPriv, pScrni->pScreen, clipBoxes); 953 } 954 955 return Success; 956} 957 958static XF86VideoEncodingPtr 959Z4lNewEncoding(XF86VideoEncodingPtr * encs, int *nencs) 960{ 961 XF86VideoEncodingPtr enc; 962 XF86VideoEncodingPtr tencs = 963 (XF86VideoEncodingPtr) xrealloc(*encs, sizeof(*tencs) * (*nencs + 1)); 964 965 if (tencs == NULL) 966 return NULL; 967 968 *encs = tencs; 969 enc = &tencs[*nencs]; 970 ++*nencs; 971 memset(enc, 0, sizeof(*enc)); 972 973 return enc; 974} 975 976static void 977Z4lEncodingName(char *ename, int l, char *inp_name, char *std_name, char *fmt) 978{ 979 int i, ch; 980 981 while ((ch = *inp_name++) != 0) { 982 if (isalnum(ch) == 0) 983 continue; 984 if (--l <= 0) 985 goto xit; 986 *ename++ = ch; 987 } 988 989 if (--l <= 0) 990 goto xit; 991 992 *ename++ = '-'; 993 994 while ((ch = *std_name++) != 0) { 995 if (isalnum(ch) == 0) 996 continue; 997 if (--l <= 0) 998 goto xit; 999 *ename++ = ch; 1000 } 1001 1002 if (--l <= 0) 1003 goto xit; 1004 1005 *ename++ = '-'; 1006 i = 4; 1007 1008 while (--i >= 0 && (ch = *fmt++) != 0) { 1009 if (isalnum(ch) == 0) 1010 continue; 1011 if (--l <= 0) 1012 goto xit; 1013 *ename++ = ch; 1014 } 1015 1016 xit: 1017 *ename = 0; 1018} 1019 1020static int 1021Z4lAddEncoding(XF86VideoEncodingPtr enc, char *name, int id, int width, 1022 int height, int numer, int denom, int inp, v4l2_std_id std, 1023 unsigned int fmt) 1024{ 1025 int l, n; 1026 t_std_data *sp; 1027 char *cp; 1028 n = sizeof(int) - 1; 1029 l = strlen(&name[0]) + 1; 1030 l = (l + n) & ~n; 1031 n = l + sizeof(*sp); 1032 cp = (char *)xalloc(n); 1033 1034 if (cp == NULL) 1035 return 0; 1036 1037 sp = (t_std_data *) (cp + l); 1038 enc->id = id; 1039 strcpy(cp, &name[0]); 1040 enc->name = cp; 1041 enc->width = width; 1042 enc->height = height; 1043 enc->rate.numerator = numer; 1044 enc->rate.denominator = denom; 1045 sp->inp = inp; 1046 sp->std = std; 1047 sp->fmt = fmt; 1048 DBLOG(1, "enc %s\n", &name[0]); 1049 1050 return 1; 1051} 1052 1053static XF86ImagePtr 1054Z4lNewImage(XF86ImagePtr * imgs, int *nimgs) 1055{ 1056 XF86ImagePtr img; 1057 XF86ImagePtr timgs = 1058 (XF86ImagePtr) xrealloc(*imgs, sizeof(*timgs) * (*nimgs + 1)); 1059 1060 if (timgs == NULL) 1061 return NULL; 1062 1063 *imgs = timgs; 1064 img = &timgs[*nimgs]; 1065 ++*nimgs; 1066 memset(img, 0, sizeof(*img)); 1067 1068 return img; 1069} 1070 1071static int 1072Z4lAddImage(XF86ImagePtr img, XF86ImagePtr ip) 1073{ 1074 *img = *ip; 1075 DBLOG(1, "img %4.4s\n", (char *)&img->id); 1076 return 1; 1077} 1078 1079static XF86AttributePtr 1080Z4lNewAttribute(XF86AttributePtr * attrs, int *nattrs) 1081{ 1082 XF86AttributePtr attr; 1083 XF86AttributePtr tattrs = 1084 (XF86AttributePtr) xrealloc(*attrs, sizeof(*tattrs) * (*nattrs + 1)); 1085 1086 if (tattrs == NULL) 1087 return NULL; 1088 1089 *attrs = tattrs; 1090 attr = &tattrs[*nattrs]; 1091 ++*nattrs; 1092 memset(attr, 0, sizeof(*attr)); 1093 1094 return attr; 1095} 1096 1097static void 1098Z4lAttributeName(char *bp, int l, char *cp) 1099{ 1100 int ch; 1101 char *atomNm = bp; 1102 1103 if (l > 0) { 1104 *bp++ = 'X'; 1105 --l; 1106 } 1107 if (l > 0) { 1108 *bp++ = 'V'; 1109 --l; 1110 } 1111 if (l > 0) { 1112 *bp++ = '_'; 1113 --l; 1114 } 1115 1116 while (l > 0 && (ch = *cp++) != 0) { 1117 if (isalnum(ch) == 0) 1118 continue; 1119 *bp++ = toupper(ch); 1120 } 1121 1122 *bp = 0; 1123 MakeAtom(&atomNm[0], strlen(&atomNm[0]), TRUE); 1124} 1125 1126static int 1127Z4lAddAttribute(XF86AttributePtr attr, char *name, 1128 int min, int max, int flags) 1129{ 1130 char *cp = (char *)xalloc(strlen((char *)&name[0]) + 1); 1131 1132 if (cp == NULL) 1133 return 0; 1134 1135 attr->name = cp; 1136 strcpy(&attr->name[0], name); 1137 attr->min_value = min; 1138 attr->max_value = max; 1139 attr->flags = flags; 1140 DBLOG(1, "attr %s\n", attr->name); 1141 1142 return 1; 1143} 1144 1145static XF86VideoAdaptorPtr 1146Z4lNewAdaptor(XF86VideoAdaptorPtr ** adpts, int *nadpts, int nattrs) 1147{ 1148 int n; 1149 Z4lPortPrivRec *pPriv; 1150 XF86VideoAdaptorPtr adpt, *tadpts; 1151 1152 tadpts = (XF86VideoAdaptorPtr *) xrealloc(*adpts, 1153 sizeof(*tadpts) * (*nadpts + 1)); 1154 1155 if (tadpts == NULL) 1156 return NULL; 1157 1158 *adpts = tadpts; 1159 n = sizeof(*adpt) + sizeof(*pPriv) + 1 * sizeof(*adpt->pPortPrivates); 1160 n += (nattrs - 1) * sizeof(pPriv->attrIds[0]); 1161 adpt = (XF86VideoAdaptorPtr) xalloc(n); 1162 1163 if (adpt == NULL) 1164 return NULL; 1165 1166 memset(adpt, 0, n); 1167 tadpts[*nadpts] = adpt; 1168 ++*nadpts; 1169 adpt->pPortPrivates = (DevUnion *) & adpt[1]; 1170 pPriv = (Z4lPortPrivRec *) & adpt->pPortPrivates[1]; 1171 adpt->pPortPrivates[0].ptr = (pointer) pPriv; 1172 pPriv->adpt = adpt; 1173 adpt->nPorts = 1; 1174 1175 return adpt; 1176} 1177 1178static int 1179Z4lSetPortAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value, 1180 pointer data) 1181{ 1182 Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 1183 XF86VideoAdaptorPtr adpt; 1184 XF86AttributePtr attr; 1185 struct v4l2_control ctrl; 1186 int i, nattrs, attrId, val; 1187 char *name = NameForAtom(attribute); 1188 int old_fd = pPriv->fd; 1189 1190 DBLOG(1, "Z4lSetPortAttribute(%#lx,%d) '%s'\n", (unsigned long)attribute, 1191 (int)value, name != NULL ? name : "_null_"); 1192 1193 if (name == NULL) 1194 return BadImplementation; 1195 if (old_fd < 0 && z4l_open_device(pPriv) < 0) 1196 return BadAccess; 1197 1198 adpt = pPriv->adpt; 1199 attr = adpt->pAttributes; 1200 nattrs = adpt->nAttributes; 1201 1202 for (i = 0; i < nattrs; ++i, ++attr) 1203 if (strcmp(attr->name, name) == 0) 1204 break; 1205 1206 if (i >= nattrs) 1207 return BadMatch; 1208 1209 attrId = pPriv->attrIds[i]; 1210 val = value; 1211 1212 switch (attrId) { 1213 case ATTR_ENCODING_ID: 1214 z4l_ovly_set_encoding(pPriv, val); 1215 break; 1216 case ATTR_KEYMODE_ID: 1217 z4l_ovly_set_keymode(pPriv, val); 1218 REGION_EMPTY(pScrni->pScreen, &pPriv->clips); 1219 z4l_setup_colorkey(pPriv, pScrni->pScreen, &pPriv->clips); 1220 break; 1221 case ATTR_COLORKEY_ID: 1222 z4l_ovly_set_colorkey(pPriv, val); 1223 break; 1224 default: 1225 memset(&ctrl, 0, sizeof(ctrl)); 1226 ctrl.id = attrId + V4L2_CID_BASE; 1227 ctrl.value = val; 1228 if (IoCtl(pPriv->fd, VIDIOC_S_CTRL, &ctrl, 1) != 0) 1229 return BadMatch; 1230 break; 1231 } 1232 1233 if (old_fd < 0) 1234 z4l_close_device(pPriv); 1235 1236 return Success; 1237} 1238 1239static int 1240Z4lGetPortAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 * value, 1241 pointer data) 1242{ 1243 Z4lPortPrivRec *pPriv = (Z4lPortPrivRec *) data; 1244 XF86VideoAdaptorPtr adpt; 1245 XF86AttributePtr attr; 1246 struct v4l2_control ctrl; 1247 int i, nattrs, attrId, val; 1248 char *name = NameForAtom(attribute); 1249 int old_fd = pPriv->fd; 1250 1251 DBLOG(1, "Z4lGetPortAttribute(%#lx) '%s'\n", 1252 (unsigned long)attribute, name != NULL ? name : "_null_"); 1253 1254 if (name == NULL) 1255 return BadImplementation; 1256 if (old_fd < 0 && z4l_open_device(pPriv) < 0) 1257 return BadAccess; 1258 1259 adpt = pPriv->adpt; 1260 attr = adpt->pAttributes; 1261 nattrs = adpt->nAttributes; 1262 1263 for (i = 0; i < nattrs; ++i, ++attr) 1264 if (strcmp(attr->name, name) == 0) 1265 break; 1266 1267 if (i >= nattrs) 1268 return BadMatch; 1269 1270 attrId = pPriv->attrIds[i]; 1271 val = 0; 1272 1273 switch (attrId) { 1274 case ATTR_ENCODING_ID: 1275 z4l_ovly_get_encoding(pPriv, &val); 1276 *value = val; 1277 break; 1278 case ATTR_KEYMODE_ID: 1279 z4l_ovly_get_keymode(pPriv, &val); 1280 *value = val; 1281 break; 1282 case ATTR_COLORKEY_ID: 1283 z4l_ovly_get_colorkey(pPriv, &val); 1284 break; 1285 default: 1286 memset(&ctrl, 0, sizeof(ctrl)); 1287 ctrl.id = attrId + V4L2_CID_BASE; 1288 if (IoCtl(pPriv->fd, VIDIOC_G_CTRL, &ctrl, 1) != 0) 1289 return BadMatch; 1290 val = ctrl.value; 1291 break; 1292 } 1293 1294 if (old_fd < 0) 1295 z4l_close_device(pPriv); 1296 1297 *value = val; 1298 1299 return Success; 1300} 1301 1302static void (*oldAdjustFrame) (int scrnIndex, int x, int y, int flags) = NULL; 1303 1304static void 1305Z4lAdjustFrame(int scrnIndex, int x, int y, int flags) 1306{ 1307 int i; 1308 XF86VideoAdaptorPtr adpt; 1309 Z4lPortPrivRec *pPriv; 1310 1311 DBLOG(3, "Z4lAdjustFrame(%d,%d,%d)\n", x, y, flags); 1312 z4l_x_offset = x; 1313 z4l_y_offset = y; 1314 oldAdjustFrame(scrnIndex, x, y, flags); 1315 1316 /* xv adjust does not handle putvideo case */ 1317 for (i = 0; i < Z4l_nAdaptors; ++i) { 1318 adpt = Z4l_pAdaptors[i]; 1319 pPriv = (Z4lPortPrivRec *) adpt->pPortPrivates[0].ptr; 1320 if (pPriv->run > 0) { 1321 pPriv->drw_is_set = 0; 1322 z4l_ovly_rect(pPriv, 1323 pPriv->src_x, pPriv->src_y, pPriv->src_w, pPriv->src_h, 1324 pPriv->drw_x, pPriv->drw_y, pPriv->drw_w, pPriv->drw_h); 1325 } 1326 } 1327} 1328 1329static int 1330Z4lInit(ScrnInfoPtr pScrni, XF86VideoAdaptorPtr ** adaptors) 1331{ 1332 int i, id, fd, dev, enable, has_video, has_colorkey; 1333 int ctl, cinp, inp, std, fmt, has_image; 1334 int nadpts, nattrs, nencs, cenc, nimgs; 1335 int numer, denom, width, height; 1336 unsigned int pixfmt, cpixfmt, opixfmt; 1337 XF86VideoAdaptorPtr *adpts, adpt; 1338 XF86AttributePtr attrs, attr; 1339 XF86VideoEncodingPtr encs, enc; 1340 XF86ImagePtr ip, img, imgs; 1341 Z4lPortPrivRec *pPriv; 1342 char *dp, *msg; 1343 char enc_name[256], attr_name[256]; 1344 int attrIds[V4L2_CID_LASTP1 - V4L2_CID_BASE + ATTR_MAX_ID]; 1345 struct v4l2_capability capability; 1346 v4l2_std_id cstd_id, std_id; 1347 struct v4l2_standard standard; 1348 struct v4l2_format format, cfmt; 1349 struct v4l2_input input; 1350 struct v4l2_fmtdesc fmtdesc; 1351 struct v4l2_queryctrl queryctrl; 1352 struct v4l2_framebuffer fbuf; 1353 1354 DBLOG(1, "Init\n"); 1355 if (oldAdjustFrame == NULL) { 1356 oldAdjustFrame = pScrni->AdjustFrame; 1357 pScrni->AdjustFrame = Z4lAdjustFrame; 1358 } 1359 1360 fd = -1; 1361 enc = NULL; 1362 encs = NULL; 1363 nencs = 0; 1364 img = NULL; 1365 imgs = NULL; 1366 nimgs = 0; 1367 attr = NULL; 1368 attrs = NULL; 1369 nattrs = 0; 1370 adpt = NULL; 1371 adpts = NULL; 1372 nadpts = 0; 1373 has_video = has_image = has_colorkey = 0; 1374 1375 for (dev = 0; z4l_dev_paths[dev] != NULL; ++dev) { 1376 fd = open(z4l_dev_paths[dev], O_RDWR, 0); 1377 if (fd < 0) 1378 continue; 1379 DBLOG(1, "%s open ok\n", z4l_dev_paths[dev]); 1380 msg = NULL; 1381 enable = 1; 1382 if (IoCtl(fd, VIDIOC_QUERYCAP, &capability, 1) < 0) 1383 msg = "bad querycap"; 1384 else if ((capability.capabilities & V4L2_CAP_VIDEO_OVERLAY) == 0) 1385 msg = "no overlay"; 1386 else if ((capability.capabilities & V4L2_CAP_STREAMING) == 0) 1387 msg = "no streaming"; 1388#ifdef NONBLK_IO 1389 else if (IoCtl(fd, FIONBIO, &enable, 1) != 0) 1390 msg = "cant enable non-blocking io"; 1391#endif 1392 if (msg == NULL) { 1393 memset(&format, 0, sizeof(format)); 1394 format.type = 0x100; 1395 if (IoCtl(fd, VIDIOC_G_FMT, &format, 1) != 0) 1396 msg = "no src/dst ovly fmt"; 1397 } 1398 if (msg != NULL) { 1399 DBLOG(0, "%s %s\n", z4l_dev_paths[dev], msg); 1400 close(fd); 1401 continue; 1402 } 1403 1404 memset(&cfmt, 0, sizeof(cfmt)); 1405 cfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1406 if (IoCtl(fd, VIDIOC_G_FMT, &cfmt, 1) < 0) 1407 goto fail; 1408 if (IoCtl(fd, VIDIOC_G_STD, &cstd_id, 1) < 0) 1409 goto fail; 1410 if (IoCtl(fd, VIDIOC_G_INPUT, &cinp, 1) < 0) 1411 goto fail; 1412 cpixfmt = cfmt.fmt.pix.pixelformat; 1413 cenc = 0; 1414 for (inp = 0;; ++inp) { 1415 memset(&input, 0, sizeof(input)); 1416 input.index = inp; 1417 if (IoCtl(fd, VIDIOC_ENUMINPUT, &input, 0) < 0) 1418 break; 1419 id = inp; 1420 if (IoCtl(fd, VIDIOC_S_INPUT, &id, 1) < 0) 1421 goto fail; 1422 for (std = 0;; ++std) { 1423 memset(&standard, 0, sizeof(standard)); 1424 standard.index = std; 1425 if (IoCtl(fd, VIDIOC_ENUMSTD, &standard, 0) < 0) 1426 break; 1427 std_id = standard.id; 1428 denom = standard.frameperiod.denominator; 1429 numer = standard.frameperiod.numerator; 1430 if (IoCtl(fd, VIDIOC_S_STD, &std_id, 1) < 0) 1431 continue; 1432 memset(&format, 0, sizeof(format)); 1433 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1434 if (IoCtl(fd, VIDIOC_G_FMT, &format, 1) < 0) 1435 continue; 1436 width = format.fmt.pix.width; 1437 height = format.fmt.pix.height; 1438 for (fmt = 0;; ++fmt) { 1439 memset(&fmtdesc, 0, sizeof(fmtdesc)); 1440 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1441 fmtdesc.index = fmt; 1442 if (IoCtl(fd, VIDIOC_ENUM_FMT, &fmtdesc, 0) < 0) 1443 break; 1444 pixfmt = fmtdesc.pixelformat; 1445 ip = &pixfmts[0]; 1446 for (i = sizeof(pixfmts) / sizeof(pixfmts[0]); --i >= 0; 1447 ++ip) 1448 if (z4l_fourcc_pixfmt(ip->id) == pixfmt) 1449 break; 1450 1451 if (i >= 0) { 1452 id = nencs; 1453 has_video = 1; 1454 if ((enc = Z4lNewEncoding(&encs, &nencs)) == NULL) 1455 goto fail; 1456 Z4lEncodingName(&enc_name[0], sizeof(enc_name), 1457 (char *)&input.name[0], 1458 (char *)&standard.name[0], (char *)&pixfmt); 1459 if (Z4lAddEncoding(enc, &enc_name[0], id, width, 1460 height, denom, numer, inp, std_id, 1461 pixfmt) == 0) 1462 goto fail; 1463 if (std_id == cstd_id && inp == cinp 1464 && pixfmt == cpixfmt) 1465 cenc = id; 1466 } 1467 } 1468 } 1469 } 1470 1471 if (IoCtl(fd, VIDIOC_S_INPUT, &cinp, 1) < 0) 1472 goto fail; 1473 if (IoCtl(fd, VIDIOC_S_STD, &cstd_id, 1) < 0) 1474 goto fail; 1475 if (IoCtl(fd, VIDIOC_S_FMT, &cfmt, 1) < 0) 1476 goto fail; 1477 1478 if (encs == NULL) { 1479 DBLOG(0, "no encodings\n"); 1480 goto fail; 1481 } 1482 1483 for (fmt = 0;; ++fmt) { 1484 memset(&fmtdesc, 0, sizeof(fmtdesc)); 1485 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; 1486 fmtdesc.index = fmt; 1487 if (IoCtl(fd, VIDIOC_ENUM_FMT, &fmtdesc, 0) < 0) 1488 break; 1489 pixfmt = fmtdesc.pixelformat; 1490 ip = &pixfmts[0]; 1491 for (i = sizeof(pixfmts) / sizeof(pixfmts[0]); --i >= 0; ++ip) 1492 if (z4l_fourcc_pixfmt(ip->id) == pixfmt) 1493 break; 1494 1495 if (i >= 0) { 1496 has_image = 1; 1497 if ((img = Z4lNewImage(&imgs, &nimgs)) == NULL) 1498 goto fail; 1499 if (Z4lAddImage(img, ip) == 0) 1500 goto fail; 1501 } 1502 } 1503 1504 if (nimgs > 0) { 1505 id = nencs; 1506 if ((enc = Z4lNewEncoding(&encs, &nencs)) == NULL) 1507 goto fail; 1508 if (Z4lAddEncoding(enc, "XV_IMAGE", id, MAX_OVLY_WIDTH, 1509 MAX_OVLY_HEIGHT, 0, 0, 0, 0, pixfmt) == 0) 1510 goto fail; 1511 } 1512 1513 ctl = 0; 1514 for (ctl = 0; ctl < (V4L2_CID_LASTP1 - V4L2_CID_BASE); ++ctl) { 1515 memset(&queryctrl, 0, sizeof(queryctrl)); 1516 queryctrl.id = V4L2_CID_BASE + ctl; 1517 if (IoCtl(fd, VIDIOC_QUERYCTRL, &queryctrl, 0) < 0) 1518 continue; 1519 if (queryctrl.type != V4L2_CTRL_TYPE_INTEGER && 1520 queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN) 1521 continue; 1522 attrIds[nattrs] = ctl; 1523 if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) 1524 goto fail; 1525 Z4lAttributeName(&attr_name[0], sizeof(attr_name), 1526 (char *)&queryctrl.name[0]); 1527 if (Z4lAddAttribute(attr, &attr_name[0], 1528 queryctrl.minimum, queryctrl.maximum, 1529 XvSettable | XvGettable) == 0) 1530 goto fail; 1531 } 1532 attrIds[nattrs] = ATTR_ENCODING_ID; 1533 if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) 1534 goto fail; 1535 Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_ENCODING); 1536 if (Z4lAddAttribute(attr, &attr_name[0], 0, nencs - 1, 1537 XvSettable | XvGettable) == 0) 1538 goto fail; 1539 memset(&fbuf, 0, sizeof(fbuf)); 1540 if (IoCtl(fd, VIDIOC_G_FBUF, &fbuf, 1) < 0) 1541 goto fail; 1542 opixfmt = fbuf.fmt.pixelformat; 1543 1544 if ((fbuf.capability & V4L2_FBUF_CAP_CHROMAKEY) != 0) { 1545 attrIds[nattrs] = ATTR_KEYMODE_ID; 1546 if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) 1547 goto fail; 1548 Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_KEYMODE); 1549 if (Z4lAddAttribute(attr, &attr_name[0], 0, 1, 1550 XvSettable | XvGettable) == 0) 1551 goto fail; 1552 attrIds[nattrs] = ATTR_COLORKEY_ID; 1553 if ((attr = Z4lNewAttribute(&attrs, &nattrs)) == NULL) 1554 goto fail; 1555 Z4lAttributeName(&attr_name[0], sizeof(attr_name), ATTR_COLORKEY); 1556 if (Z4lAddAttribute(attr, &attr_name[0], 0, 0xffffff, 1557 XvSettable | XvGettable) == 0) 1558 goto fail; 1559 has_colorkey = 1; 1560 } 1561 1562 dp = xalloc(strlen((char *)&capability.card[0]) + 1); 1563 if (dp == NULL) 1564 goto fail; 1565 strcpy(dp, (char *)&capability.card[0]); 1566 if ((adpt = Z4lNewAdaptor(&adpts, &nadpts, nattrs)) == NULL) 1567 goto fail; 1568 adpt->type = XvWindowMask | XvInputMask; 1569 if (has_video != 0) 1570 adpt->type |= XvVideoMask; 1571 if (has_image != 0) 1572 adpt->type |= XvImageMask; 1573 adpt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 1574 adpt->name = dp; 1575 adpt->type = XvInputMask | XvWindowMask | XvVideoMask | XvImageMask; 1576 adpt->pEncodings = encs; 1577 adpt->nEncodings = nencs; 1578 adpt->pFormats = &Formats[0]; 1579 adpt->nFormats = sizeof(Formats) / sizeof(Formats[0]); 1580 adpt->pAttributes = attrs; 1581 adpt->nAttributes = nattrs; 1582 attrs = NULL; 1583 nattrs = 0; 1584 adpt->pImages = imgs; 1585 adpt->nImages = nimgs; 1586 imgs = NULL; 1587 nimgs = 0; 1588 adpt->PutVideo = Z4lPutVideo; 1589 adpt->StopVideo = Z4lStopVideo; 1590 adpt->SetPortAttribute = Z4lSetPortAttribute; 1591 adpt->GetPortAttribute = Z4lGetPortAttribute; 1592 adpt->QueryBestSize = Z4lQueryBestSize; 1593 adpt->PutImage = Z4lPutImage; 1594 adpt->QueryImageAttributes = Z4lQueryImageAttributes; 1595 pPriv = (Z4lPortPrivRec *) adpt->pPortPrivates[0].ptr; 1596 pPriv->fd = fd; 1597 pPriv->run = -1; 1598 pPriv->dir = 0; 1599 pPriv->nbfrs = -1; 1600 pPriv->bufsz = -1; 1601 pPriv->last = -1; 1602 pPriv->pixfmt = opixfmt; 1603#if defined(REGION_NULL) 1604 REGION_NULL(pScrni->pScreen, &pPriv->clips); 1605#else 1606 REGION_INIT(pScrni->pScreen, &pPriv->clips, NullBox, 0); 1607#endif 1608 strncpy(&pPriv->dev_path[0], z4l_dev_paths[dev], 1609 sizeof(pPriv->dev_path)); 1610 pPriv->enc = &encs[cenc]; 1611 for (i = 0; i < adpt->nAttributes; ++i) 1612 pPriv->attrIds[i] = attrIds[i]; 1613 DBLOG(1, "adpt %s\n", dp); 1614 if (has_colorkey != 0) { 1615 z4l_ovly_set_colorkey(pPriv, DEFAULT_COLORKEY); 1616 z4l_ovly_set_keymode(pPriv, DEFAULT_KEYMODE); 1617 } 1618 close(fd); 1619 pPriv->fd = -1; 1620 adpt = NULL; 1621 cenc = 0; 1622 encs = NULL; 1623 nencs = 0; 1624 } 1625 1626 DBLOG(0, "init done, %d device(s) found\n", nadpts); 1627 Z4l_nAdaptors = nadpts; 1628 Z4l_pAdaptors = adpts; 1629 *adaptors = adpts; 1630 1631 return nadpts; 1632 1633 fail: 1634 if (attrs != NULL) { 1635 for (i = 0; i < nattrs; ++i) 1636 if (attrs[i].name != NULL) 1637 free(attrs[i].name); 1638 free(attrs); 1639 } 1640 1641 if (encs != NULL) { 1642 for (i = 0; i < nencs; ++i) { 1643 if (encs[i].name != NULL) 1644 free(encs[i].name); 1645 } 1646 free(encs); 1647 } 1648 1649 if (imgs != NULL) 1650 free(imgs); 1651 1652 if (adpts != NULL) { 1653 for (i = 0; i < nadpts; ++i) { 1654 if ((adpt = adpts[i]) != NULL) { 1655 if (adpt->name != NULL) 1656 free(adpt->name); 1657 if ((attrs = adpt->pAttributes) != NULL) { 1658 for (i = 0; i < adpt->nAttributes; ++i) 1659 if (attrs[i].name != NULL) 1660 free(attrs[i].name); 1661 free(attrs); 1662 } 1663 if ((encs = adpt->pEncodings) != NULL) { 1664 for (i = 0; i < adpt->nEncodings; ++i, ++enc) 1665 if (encs[i].name != NULL) 1666 free(encs[i].name); 1667 free(encs); 1668 } 1669 if ((imgs = adpt->pImages) != NULL) 1670 free(imgs); 1671 xfree(adpt); 1672 } 1673 } 1674 free(adpts); 1675 } 1676 1677 if (fd >= 0) 1678 close(fd); 1679 1680 return 0; 1681} 1682 1683static Bool 1684Z4lProbe(DriverPtr drv, int flags) 1685{ 1686 DBLOG(1, "Probe\n"); 1687 if (flags & PROBE_DETECT) 1688 return TRUE; 1689 1690 xf86XVRegisterGenericAdaptorDriver(Z4lInit); 1691 drv->refCount++; 1692 1693 return TRUE; 1694} 1695 1696static const OptionInfoRec * 1697Z4lAvailableOptions(int chipid, int busid) 1698{ 1699 return NULL; 1700} 1701 1702static void 1703Z4lIdentify(int flags) 1704{ 1705 xf86Msg(X_INFO, "z4l driver for Video4Linux\n"); 1706} 1707 1708_X_EXPORT DriverRec Z4l = { 1709 40001, 1710 "z4l", 1711 Z4lIdentify, 1712 Z4lProbe, 1713 Z4lAvailableOptions, 1714 NULL, 1715 0 1716}; 1717 1718#ifdef XFree86LOADER 1719 1720static MODULESETUPPROTO(z4lSetup); 1721 1722static XF86ModuleVersionInfo z4lVersionRec = { 1723 "ztv", 1724 MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, 1725 XORG_VERSION_CURRENT, 0, 0, 1, 1726 ABI_CLASS_VIDEODRV, ABI_VIDEODRV_VERSION, MOD_CLASS_NONE, 1727 {0, 0, 0, 0} 1728}; 1729 1730_X_EXPORT XF86ModuleData ztvModuleData = { &z4lVersionRec, z4lSetup, NULL }; 1731 1732static pointer 1733z4lSetup(pointer module, pointer opts, int *errmaj, int *errmin) 1734{ 1735 const char *osname; 1736 static Bool setupDone = FALSE; 1737 1738 if (setupDone != FALSE) { 1739 if (errmaj != NULL) 1740 *errmaj = LDR_ONCEONLY; 1741 return NULL; 1742 } 1743 1744 setupDone = TRUE; 1745 LoaderGetOS(&osname, NULL, NULL, NULL); 1746 1747 if (osname == NULL || strcmp(osname, "linux") != 0) { 1748 if (errmaj) 1749 *errmaj = LDR_BADOS; 1750 if (errmin) 1751 *errmin = 0; 1752 1753 return NULL; 1754 } 1755 1756 xf86AddDriver(&Z4l, module, 0); 1757 1758 return (pointer) 1; 1759} 1760 1761#endif 1762#endif /* !XvExtension */ 1763