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

Reply via email to