基于V4L2的Webcam应用过程详解【附源码】(4)

使用的数据结构

struct Ctx
{
 Display *display;
 int screen;
 Window window;
 GC gc;
 XVisualInfo vinfo;
 XImage *image;
 XShmSegmentInfo segment;
 SwsContext *sws;
 PixelFormat target_pixfmt;
 AVPicture pic_target;
 int v_width, v_height;
 int curr_width, curr_height;
};
typedef struct Ctx Ctx;

vs_open(...) 打开设备

void *vs_open (int v_width, int v_height)
{
 Ctx *ctx = new Ctx;
 ctx->v_width = v_width;
 ctx->v_height = v_height;
 // window
 ctx->display = XOpenDisplay(0);
 ctx->window = XCreateSimpleWindow(ctx->display, RootWindow(ctx->display, 0),
   100, 100, v_width, v_height, 0, BlackPixel(ctx->display, 0),
   WhitePixel(ctx->display, 0));
 ctx->screen = 0;
 ctx->gc = XCreateGC(ctx->display, ctx->window, 0, 0);
 
 XMapWindow(ctx->display, ctx->window);
 // current screen pix fmt
 Window root;
 unsigned int cx, cy, border, depth;
 int x, y;
 XGetGeometry(ctx->display, ctx->window, &root, &x, &y, &cx, &cy, &border, &depth);
 // visual info
 XMatchVisualInfo(ctx->display, ctx->screen, depth, DirectColor, &ctx->vinfo);
 // image
 ctx->image = XShmCreateImage(ctx->display, ctx->vinfo.visual, depth, ZPixmap, 0,
   &ctx->segment, cx, cy);
 if (!ctx->image) {
  fprintf(stderr, "%s: can't XShmCreateImage !/n", __func__);
  exit(-1);
 }
 ctx->segment.shmid = shmget(IPC_PRIVATE,
   ctx->image->bytes_per_line * ctx->image->height,
   IPC_CREAT | 0777);
 if (ctx->segment.shmid < 0) {
  fprintf(stderr, "%s: shmget err/n", __func__);
  exit(-1);
 }
 ctx->segment.shmaddr = (char*)shmat(ctx->segment.shmid, 0, 0);
 if (ctx->segment.shmaddr == (char*)-1) {
  fprintf(stderr, "%s: shmat err/n", __func__);
  exit(-1);
 }
 ctx->image->data = ctx->segment.shmaddr;
 ctx->segment.readOnly = 0;
 XShmAttach(ctx->display, &ctx->segment);
 PixelFormat target_pix_fmt = PIX_FMT_NONE;
 switch (ctx->image->bits_per_pixel) {
  case 32:
   target_pix_fmt = PIX_FMT_RGB32;
   break;
  case 24:
   target_pix_fmt = PIX_FMT_RGB24;
   break;
  default:
   break;
 }
 if (target_pix_fmt == PIX_FMT_NONE) {
  fprintf(stderr, "%s: screen depth format err/n", __func__);
  delete ctx;
  return 0;
 }
 // sws
 ctx->target_pixfmt = target_pix_fmt;
 ctx->curr_width = cx;
 ctx->curr_height = cy;
 ctx->sws = sws_getContext(v_width, v_height, PIX_FMT_YUV420P,
   cx, cy, target_pix_fmt,
   SWS_FAST_BILINEAR, 0, 0, 0);
 avpicture_alloc(&ctx->pic_target, target_pix_fmt, cx, cy);
 XFlush(ctx->display);
 return ctx;
}

vs_show()

sws_scale()                // 拉伸到当前窗口大小, 转换格式

XShmPutImage()        // 显示, 呵呵, 真的很简单

linux

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/7eebfdc9548b5eefc2b75fd5855d0697.html