📄 grabber-video4linux.cpp
字号:
} } if (strcmp(argv[1], "yuv_byteorder") == 0) { byteorder_ = atoi(argv[2]); return (TCL_OK); } if (strcmp(argv[1], "fps") == 0) { DEBUG(fprintf(stderr,"V4l: fps %s\n",argv[2])); } if (strcmp(argv[1], "type") == 0) { if (strcmp(argv[2], "auto") == 0) norm_ = VIDEO_MODE_AUTO; else if (strcmp(argv[2], "pal") == 0) norm_ = VIDEO_MODE_PAL; else if (strcmp(argv[2], "secam") == 0) norm_ = VIDEO_MODE_SECAM; else norm_ = VIDEO_MODE_NTSC; if (running_) format(); return (TCL_OK); } } return (Grabber::command(argc, argv));}void V4lGrabber::start(){ DEBUG(fprintf(stderr,"V4l: start\n")); format(); if (have_mmap) { grab_count = 0; sync_count = 0; if (-1 == ioctl(fd_, VIDIOCMCAPTURE, &gb_even)) perror("ioctl VIDIOCMCAPTURE even"); else grab_count++; if (-1 == ioctl(fd_, VIDIOCMCAPTURE, &gb_odd)) perror("ioctl VIDIOCMCAPTURE odd"); else grab_count++; } Grabber::start();}void V4lGrabber::stop(){ DEBUG(fprintf(stderr,"V4l: stop\n")); if (have_mmap) { while (grab_count > sync_count) { if (-1 == ioctl(fd_, VIDIOCSYNC, (sync_count%2) ? &one:&zero)) { perror("ioctl VIDIOCSYNC"); break; } else sync_count++; } } Grabber::stop();}int V4lGrabber::grab(){ char *fr=NULL; DEBUG(fprintf(stderr,(sync_count % 2) ? "o" : "e")); if (have_mmap) { fr = mem + (gb_buffers.offsets[ (sync_count % 2) ? 1: 0]); if (-1 == ioctl(fd_, VIDIOCSYNC, (sync_count%2) ? &one:&zero)){ perror("ioctl VIDIOCSYNC"); printf("Syncerror SyncCount %d\n",sync_count); } else sync_count++; } else { /* FIXME: read() */ } switch (cformat_) { case CF_411: case CF_CIF: if (have_422) packed422_to_planar411((char*)frame_,fr); else { // have_420P // vcvt_420p_411p(width_, height_, (char *)fr, frame_); // erwartet wird scheinbar 420P und nicht 411P *wunder* memcpy((void *)frame_, (const void *)fr, (size_t)height_*width_*3/2); } break; case CF_422: if (have_422P) memcpy((void *)frame_, (const void *)fr, (size_t)height_*width_*2); else if ( have_422 ) { packed422_to_planar422((char*)frame_,fr); } else { // have_420P vcvt_420p_422p(width_, height_, (char *)fr, frame_); } break; } if (have_mmap) { if (-1 == ioctl(fd_, VIDIOCMCAPTURE, (grab_count % 2) ? &gb_odd : &gb_even)) perror("ioctl VIDIOMCAPTURE"); else grab_count++; } suppress(frame_); saveblks(frame_); YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_); return (target_->consume(&f));}void V4lGrabber::packed422_to_planar422(char *dest, char *src){ int i; char *s, *y,*u,*v; unsigned int a, *srca; srca = (unsigned int *)src; i = (width_ * height_)/2; s = src; y = dest; u = y + width_ * height_; v = u + width_ * height_ / 2; switch (byteorder_) { case BYTE_ORDER_YUYV: while (--i) { a = *(srca++); *(y++) = a & 0xff; a >>= 8; *(u++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; a >>= 8; *(v++) = a & 0xff; } break; case BYTE_ORDER_YVYU: while (--i) { a = *(srca++); *(y++) = a & 0xff; a >>= 8; *(v++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; a >>= 8; *(u++) = a & 0xff; } break; case BYTE_ORDER_UYVY: while (--i) { a = *(srca++); *(u++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; a >>= 8; *(v++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; } break; case BYTE_ORDER_VYUY: while (--i) { a = *(srca++); *(v++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; a >>= 8; *(u++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; } break; }}void V4lGrabber::packed422_to_planar411(char *dest, char *src){ int a1,b; char *s, *y,*u,*v; unsigned int a, *srca; srca = (unsigned int *)src; s = src; y = dest; u = y + width_ * height_; v = u + width_ * height_ / 4; switch (byteorder_) { case BYTE_ORDER_YUYV: for (a1 = height_; a1 > 0; a1 -= 2) { for (b = width_; b > 0; b -= 2) { a = *(srca++); *(y++) = a & 0xff; a >>= 8; *(u++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; a >>= 8; *(v++) = a & 0xff; } for (b = width_; b > 0; b -= 2) { a = *(srca++); *(y++) = a & 0xff; a >>= 16; *(y++) = a & 0xff; } } break; case BYTE_ORDER_YVYU: for (a1 = height_; a1 > 0; a1 -= 2) { for (b = width_; b > 0; b -= 2) { a = *(srca++); *(y++) = a & 0xff; a >>= 8; *(v++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; a >>= 8; *(u++) = a & 0xff; } for (b = width_; b > 0; b -= 2) { a = *(srca++); *(y++) = a & 0xff; a >>= 16; *(y++) = a & 0xff; } } break; case BYTE_ORDER_UYVY: for (a1 = height_; a1 > 0; a1 -= 2) { for (b = width_; b > 0; b -= 2) { a = *(srca++); *(u++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; a >>= 8; *(v++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; } for (b = width_; b > 0; b -= 2) { a = *(srca++); a >>= 8; *(y++) = a & 0xff; a >>= 16; *(y++) = a & 0xff; } } break; case BYTE_ORDER_VYUY: for (a1 = height_; a1 > 0; a1 -= 2) { for (b = width_; b > 0; b -= 2) { a = *(srca++); *(v++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; a >>= 8; *(u++) = a & 0xff; a >>= 8; *(y++) = a & 0xff; } for (b = width_; b > 0; b -= 2) { a = *(srca++); a >>= 8; *(y++) = a & 0xff; a >>= 16; *(y++) = a & 0xff; } } break; }}/* Konvertierung YUV420P YUV422P * */void V4lGrabber::vcvt_420p_422p(int width, int height, void *src, void *dst){ /** \brief convert YUV 4:2:0 (planar) data into YUV 4:2:2 (planar) \param width Width of yuv data, in pixels \param height Height of yuv data, in pixels \param src beginning of YUV420 data \param dst beginning of YUV422P data */ int line, clinewidth; unsigned char *sy, *su, *sv, *ty, *tu, *tv; clinewidth = 2*width; sy = (unsigned char *)src; su = sy + width * height; sv = su + width * height / 4; ty = (unsigned char *)dst; tu = ty + width * height; tv = tu + width * height / 2; /* Copy planar lumina block */ memcpy(ty,sy,width*height); /* Copy the chroma under consideration of chroma for two lines in YUV420 */ for (line = 0; line < height; line += 2) { memcpy(tu,su,clinewidth); memcpy(tv,sv,clinewidth); // Don't increment sourceline if line = 2,6,10,14,... if( (line & 3) != 2 ){ su += width; sv += width; } tu += width; tv += width; }}/* Konvertierung YUV420P YUV411P * */void V4lGrabber::vcvt_420p_411p(int width, int height, void *src, void *dst){ /** \brief convert YUV 4:2:0 (planar) data into YUV 4:1:1 (planar) \param width Width of yuv data, in pixels \param height Height of yuv data, in pixels \param src beginning of YUV420 data \param dst beginning of YUV422P data */ int line, col, clinewidth, tr,tb; unsigned char *sy, *su, *sv, *ty, *tu, *tv; clinewidth = width*2; sy = (unsigned char *)src; su = sy + width * height; sv = su + width * height / 4; ty = (unsigned char *)dst; tu = ty + width * height; tv = tu + width * height / 4; /* Copy planar lumina block */ memcpy(ty,sy,width*height); /* Copy the chroma under consideration of chroma for two lines in YUV420 * Conversation 2lines2columns1chroma => 1line4columns1chroma */ for (line = 0; line < height; line += 2) { for (col = 0; col < clinewidth; col += 4){ tb = (*su++ + *su++) / 2; tr = (*sv++ + *sv++) / 2; *tu++ = tb; *tv++ = tr; } // Decrement sourceline if line = 2,6,10,14,... if( (line & 3) == 2 ){ su -= width; sv -= width; } } /* for (line = 0; line < height; line += 2) { for (col = 0; col < width; col += 4){ tb = (*su++ + *su++) / 2; tr = (*sv++ + *sv++) / 2; *tu++ = tb; *tv++ = tr; } su -= width/2; sv -= width/2; for (col = 0; col < width; col += 4){ tb = (*su++ + *su++) / 2; tr = (*sv++ + *sv++) / 2; *tu++ = tb; *tv++ = tr; } }*/}void V4lGrabber::format(){ struct video_channel channel; DEBUG(fprintf(stderr,"V4l: format")); fprintf(stderr,"V4l: format\n"); width_ = CIF_WIDTH *2 / decimate_; height_ = CIF_HEIGHT *2 / decimate_; if (have_422) v4lformat_=VIDEO_PALETTE_YUV422; else v4lformat_=VIDEO_PALETTE_YUV420P; switch (cformat_) { case CF_CIF: set_size_411(width_, height_); DEBUG(fprintf(stderr," cif")); break; case CF_411: set_size_411(width_, height_); DEBUG(fprintf(stderr," 411")); break; case CF_422: set_size_422(width_, height_); if (have_422P ) { v4lformat_=VIDEO_PALETTE_YUV422P; fprintf(stderr,"Capturing directly in 422 Planar\n"); } DEBUG(fprintf(stderr," 422")); break; } if (have_mmap) { gb_even.frame = 0; gb_even.format = v4lformat_; gb_even.width = width_; gb_even.height = height_; gb_odd.frame = 1; gb_odd.format = v4lformat_; gb_odd.width = width_; gb_odd.height = height_; } else { memset(&win,0,sizeof(win)); win.width = width_; win.height = height_; if (-1 == ioctl(fd_,VIDIOCSWIN,&win)) perror("ioctl VIDIOCSWIN"); if (-1 == ioctl(fd_,VIDIOCGWIN,&win)) perror("ioctl VIDIOCGWIN"); width_ = win.width; height_ = win.height; pict.palette = v4lformat_; if (-1 == ioctl(fd_,VIDIOCSPICT,&pict)) { perror("ioctl VIDIOCSPICT"); } } if (-1 == ioctl(fd_,VIDIOCGPICT,&pict)) { perror("ioctl VIDIOCGPICT"); } DEBUG(fprintf(stderr," size=%dx%d",width_,height_)); fprintf(stderr," size=%dx%d\n",width_,height_); bzero(&channel, sizeof(struct video_channel)); if (-1 == ioctl(fd_, VIDIOCGCHAN, &channel)) perror("ioctl VIDIOCGCHAN"); channel.channel = port_; channel.norm = norm_; if (-1 == ioctl(fd_, VIDIOCSCHAN, &channel)) perror("ioctl VIDIOCSCHAN"); DEBUG(fprintf(stderr," port=%d\n",port_)); DEBUG(fprintf(stderr," norm=%d\n",norm_)); fprintf(stderr," port=%d\n",port_); fprintf(stderr," norm=%d\n",norm_); allocref();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -