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