On Tue, Aug 26, 2014 at 9:12 PM, Luca Barbato <lu_z...@gentoo.org> wrote:
> +static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt) > +{ > + XCBGrabContext *c = s->priv_data; > + xcb_shm_get_image_cookie_t iq; > + xcb_shm_get_image_reply_t *img; > + xcb_drawable_t drawable = c->screen->root; > + uint8_t *data; > + int size = c->frame_size + FF_INPUT_BUFFER_PADDING_SIZE; > + int id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); > + xcb_generic_error_t *e = NULL; > + > + if (id == -1) { > + char errbuf[1024]; > + av_strerror(AVERROR(errno), errbuf, sizeof(errbuf)); > + av_log(s, AV_LOG_ERROR, "shmget %d failed: %s\n", size, errbuf); > + return AVERROR(ENOMEM); Does this have to be ENOMEM? Better return AVERROR(errno). > + } > + > + xcb_shm_attach(c->conn, c->segment, id, 0); > + > + iq = xcb_shm_get_image(c->conn, drawable, > + c->x, c->y, c->width, c->height, ~0, > + XCB_IMAGE_FORMAT_Z_PIXMAP, c->segment, 0); > + > + xcb_shm_detach(c->conn, c->segment); > + > + img = xcb_shm_get_image_reply(c->conn, iq, &e); > + > + xcb_flush(c->conn); > + > + if (e) { > + av_log(s, AV_LOG_ERROR, > + "event_error: %s: response_type:%u error_code:%u " > + "sequence:%u resource_id:%u minor_code:%u major_code:%u\n", > + xcb_event_get_error_label(e->error_code), e->response_type, > + e->error_code, e->sequence, e->resource_id, e->minor_code, > + e->major_code); The message could be enhanced. > + > + shmctl(id, IPC_RMID, 0); > + return AVERROR(EACCES); > + } > + > + free(img); > + > + data = shmat(id, NULL, 0); > + shmctl(id, IPC_RMID, 0); > + > + if ((intptr_t)data == -1) > + return AVERROR(errno); > + > + pkt->buf = av_buffer_create(data, size, dealloc_shm, NULL, 0); > + > + if (!pkt->buf) { > + shmdt(data); > + return AVERROR(ENOMEM); > + } > + > + pkt->data = pkt->buf->data; > + pkt->size = c->frame_size; > + > + return 0; > +} > +#endif /* HAVE_SYS_SHM_H */ > + > +#define BLEND(target, source, alpha) \ > + (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255 > + > +static int xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt, > + xcb_query_pointer_reply_t *p, > + xcb_get_geometry_reply_t *geo) > +{ > + XCBGrabContext *gr = s->priv_data; > + uint32_t *cursor; > + uint8_t *image = pkt->data; > + int stride = gr->bpp / 8; > + xcb_xfixes_get_cursor_image_cookie_t cc; > + xcb_xfixes_get_cursor_image_reply_t *ci; > + int cx, cy, x, y, w, h, c_off, i_off; > + > + cc = xcb_xfixes_get_cursor_image(gr->conn); > + ci = xcb_xfixes_get_cursor_image_reply(gr->conn, cc, NULL); > + cursor = xcb_xfixes_get_cursor_image_cursor_image(ci); > + > + if (!cursor) > + return 0; > + > + cx = ci->x - ci->xhot; > + cy = ci->y - ci->yhot; > + > + x = FFMAX(cx, gr->x); > + y = FFMAX(cy, gr->y); > + > + w = FFMIN(cx + ci->width, gr->x + gr->width) - x; > + h = FFMIN(cy + ci->height, gr->y + gr->height) - y; > + > + c_off = x - cx; > + i_off = x - gr->x; > + > + cursor += (y - cy) * ci->width; > + image += (y - gr->y) * gr->width * stride; > + > + for (y = 0; y < h; y++) { > + cursor += c_off; > + image += i_off * stride; > + for (x = 0; x < w; x++, cursor++, image += stride) { > + int r, g, b, a; > + > + r = *cursor & 0xff; > + g = (*cursor >> 8) & 0xff; > + b = (*cursor >> 16) & 0xff; > + a = (*cursor >> 24) & 0xff; > + > + if (!a) > + continue; > + > + if (a == 255) { > + image[0] = r; > + image[1] = g; > + image[2] = b; > + } else { > + image[0] = BLEND(r, image[0], a); > + image[1] = BLEND(g, image[1], a); > + image[2] = BLEND(b, image[2], a); > + } > + > + } > + cursor += ci->width - w - c_off; > + image += (gr->width - w - i_off) * stride; > + } > + > + free(ci); > + > + return 0; > +} > + > +static void xcbgrab_update_region(AVFormatContext *s) > +{ > + XCBGrabContext *c = s->priv_data; > + const uint32_t args[] = { c->x - c->region_border, > + c->y - c->region_border }; > + > + xcb_configure_window(c->conn, > + c->window, > + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, > + args); > +} > + > +static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt) > +{ > + XCBGrabContext *c = s->priv_data; > + xcb_query_pointer_cookie_t pc; > + xcb_get_geometry_cookie_t gc; > + xcb_query_pointer_reply_t *p = NULL; > + xcb_get_geometry_reply_t *geo = NULL; > + int ret = 0; > + > + wait_frame(s, pkt); > + > + if (c->follow_mouse || c->draw_mouse) { > + pc = xcb_query_pointer(c->conn, c->screen->root); > + gc = xcb_get_geometry(c->conn, c->screen->root); > + p = xcb_query_pointer_reply(c->conn, pc, NULL); > + geo = xcb_get_geometry_reply(c->conn, gc, NULL); > + } > + > + if (c->follow_mouse) { > + xcbgrab_reposition(s, p, geo); > + if (c->show_region) > + xcbgrab_update_region(s); > + } > + > +#if HAVE_SYS_SHM_H > + if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) > + c->has_shm = 0; > +#endif > + if (!c->has_shm) > + ret = xcbgrab_frame(s, pkt); Unchecked return code > + > + if (c->draw_mouse) > + ret = xcbgrab_draw_mouse(s, pkt, p, geo); > + > + free(p); > + free(geo); > + > + return ret; > +} [...] > + > +static av_cold int xcbgrab_read_header(AVFormatContext *s) > +{ > + XCBGrabContext *c = s->priv_data; > + int screen_num, ret; > + const xcb_setup_t *setup; > + > + c->conn = xcb_connect(s->filename, &screen_num); > + if ((ret = xcb_connection_has_error(c->conn))) { > + av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d\n", > + s->filename ? s->filename : "default", ret); > + return AVERROR(EIO); > + } > + setup = xcb_get_setup(c->conn); > + > + c->screen = get_screen(setup, screen_num); > + if (!c->screen) { > + av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n", > + screen_num); Missing return? > + } > + > + c->segment = xcb_generate_id(c->conn); > + c->has_shm = check_shm(c->conn); > + > + ret = create_stream(s); > + > + if (ret < 0) { > + xcbgrab_read_close(s); > + return ret; > + } > + > + if (c->draw_mouse) { > + if (!(c->draw_mouse = check_xfixes(c->conn))) { > + av_log(s, AV_LOG_WARNING, > + "XFixes not available, cannot draw the mouse.\n"); > + } > + if (c->bpp < 24) { > + avpriv_report_missing_feature(s, "%d bits per pixel screen", > + c->bpp); > + c->draw_mouse = 0; Ditto? [...] Timothy _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel