使用的数据结构
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() // 显示, 呵呵, 真的很简单