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

vs_show(...) 主要代码都是处理窗口变化的

int vs_show (void *ctx, unsigned char *data[4], int stride[4])
{
 // 首选检查 sws 是否有效, 根据当前窗口大小决定
 Ctx *c = (Ctx*)ctx;
 Window root;
 int x, y;
 unsigned int cx, cy, border, depth;
 XGetGeometry(c->display, c->window, &root, &x, &y, &cx, &cy, &border, &depth);
 if (cx != c->curr_width || cy != c->curr_height) {
  avpicture_free(&c->pic_target);
  sws_freeContext(c->sws);
  c->sws = sws_getContext(c->v_width, c->v_height, PIX_FMT_YUV420P,
    cx, cy, c->target_pixfmt,
    SWS_FAST_BILINEAR, 0, 0, 0);
  avpicture_alloc(&c->pic_target, c->target_pixfmt, cx, cy);
  c->curr_width = cx;
  c->curr_height = cy;
  // re create image
  XShmDetach(c->display, &c->segment);
  shmdt(c->segment.shmaddr);
  shmctl(c->segment.shmid, IPC_RMID, 0);
  XDestroyImage(c->image);
  c->image = XShmCreateImage(c->display, c->vinfo.visual, depth, ZPixmap, 0,
   &c->segment, cx, cy);
  c->segment.shmid = shmget(IPC_PRIVATE,
    c->image->bytes_per_line * c->image->height,
    IPC_CREAT | 0777);
  c->segment.shmaddr = (char*)shmat(c->segment.shmid, 0, 0);
  c->image->data = c->segment.shmaddr;
  c->segment.readOnly = 0;
  XShmAttach(c->display, &c->segment);
 }
 //
 sws_scale(c->sws, data, stride, 0, c->v_height, c->pic_target.data, c->pic_target.linesize);
 // cp to image
 unsigned char *p = c->pic_target.data[0], *q = (unsigned char*)c->image->data;
 int xx = MIN(c->image->bytes_per_line, c->pic_target.linesize[0]);
 for (int i = 0; i < c->curr_height; i++) {
  memcpy(q, p, xx);
  p += c->image->bytes_per_line;
  q += c->pic_target.linesize[0];
 }
 // 显示到 X 上
 XShmPutImage(c->display, c->window, c->gc, c->image, 0, 0, 0, 0, c->curr_width, c->curr_height, 1);
 return 1;
}

linux

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

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