[vlc-devel] [PATCH 2/2][RFC] VAAPI XCB video output

Jean-Baptiste Kempf jb at videolan.org
Tue Aug 23 20:16:26 CEST 2016


On 23 Aug, Petri Hintukainen wrote :
> ---
>  modules/MODULES_LIST        |   2 +
>  modules/Makefile.am         |   1 +
>  modules/hw/va/Makefile.am   |  19 ++
>  modules/hw/va/chroma.c      | 187 ++++++++++++++++
>  modules/hw/va/vlc_va.c      | 528 ++++++++++++++++++++++++++++++++++++++++++++
>  modules/hw/va/vlc_va.h      | 152 +++++++++++++
>  modules/hw/va/xcb_display.c | 485 ++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 1374 insertions(+)

Missing NEWS and po/POTFILES.in

> +include hw/va/Makefile.am
>  include hw/vdpau/Makefile.am

Do we want more Makefile.am here? Rémi?

(btw, why is not hw/mmal/ listed?)


> +static picture_t *UploadSurface(filter_t *filter, picture_t *src)
> +{
> +    filter_sys_t  *sys = filter->p_sys;
> +    VAStatus       status;
> +    picture_t     *dst = NULL;
> +    picture_sys_t *picsys;
> +
> +    dst = filter_NewPicture(filter);
> +    if (dst == NULL) {
> +        msg_Err(filter, "filter_NewPicture failed\n");

\n is unnecessary.

OK.

> +static int OutputOpen(vlc_object_t *obj)
> +{
> +    if (filter->fmt_in.video.orientation != filter->fmt_out.video.orientation) {
> +        return VLC_EGENERIC;

Any simple way of handling rotations?

> +    if (status != VA_STATUS_SUCCESS) {
> +        msg_Err(filter, "vlc_va_TestPutImage() failed: %d\n", status);
> +        goto error;
as above.

> +/*****************************************************************************
> + * vlc_va.c: VAAPI helper for VLC
> + *****************************************************************************


> +    msg_Info(o, "VA-API: v%d.%d (%s)\n", major, minor, vendor);
I'd argue this requires a better message.

> +picture_pool_t *vlc_va_PoolAlloc(vlc_object_t *o, VADisplay va_dpy, unsigned requested_count,
> +                                 const video_format_t *restrict fmt, unsigned int va_rt_format)
> +{
> +    picture_t   *pics[requested_count];
> +    VASurfaceID  va_surface_ids[requested_count];
> +    VAStatus     status;
> +    unsigned     count;
> +
> +    status = vaCreateSurfaces(va_dpy, va_rt_format,
> +                              fmt->i_visible_width, fmt->i_visible_height,
> +                              va_surface_ids, requested_count, NULL, 0);
> +    if (status != VA_STATUS_SUCCESS) {
> +        msg_Err(o, "vaCreateSurfaces(%d) failed: %d\n", va_rt_format, status);
idem.

> +#if 0
> +    /* too late to test here ? */
> +    status = vlc_va_TestPutImage(va_dpy, &va_format,
> +                                 va_surface_ids[0], NULL,
> +                                 fmt->i_visible_width, fmt->i_visible_height);
> +#endif

Why would it be too late?

> +static int CopyPicture(vlc_object_t *o,
> +                       VAImage *va_image, uint8_t *base,
> +                       int dst_x, int dst_y, const picture_t *src)
> +{
> +    plane_t dst_planes[3];

3?

If so, don't we need to assert on src->i_planes to be <= 3?

> +
> +    for (int i = 0; i < src->i_planes; i++) {
> +        dst_planes[i].p_pixels        = base + va_image->offsets[i];
> +        dst_planes[i].i_pitch         = va_image->pitches[i];
> +        dst_planes[i].i_visible_pitch = va_image->pitches[i];
> +        dst_planes[i].i_lines         = src->p[i].i_visible_lines;
> +        dst_planes[i].i_visible_lines = src->p[i].i_visible_lines;
> +        dst_planes[i].i_pixel_pitch   = src->p[i].i_pixel_pitch;
> +    }
> +
> +    if (src->format.i_chroma == VLC_CODEC_I420 ||
> +        src->format.i_chroma == VLC_CODEC_I422 ||
> +        src->format.i_chroma == VLC_CODEC_I444) {
> +
> +        plane_t tmp = dst_planes[1];
> +        dst_planes[1] = dst_planes[2];
> +        dst_planes[2] = tmp;
> +    }
> +
> +    switch (va_image->format.fourcc) {
> +        case VA_FOURCC_ARGB:
> +        case VA_FOURCC_RGBA:
> +            dst_planes[0].p_pixels += dst_x * 4 + dst_y * dst_planes[0].i_pitch;
> +            break;
> +
> +        case VA_FOURCC_IYUV:
> +        case VA_FOURCC_YV12:
> +            dst_planes[0].p_pixels += dst_x     + dst_y     * dst_planes[0].i_pitch;
> +            dst_planes[1].p_pixels += dst_x / 2 + dst_y / 2 * dst_planes[1].i_pitch;
> +            dst_planes[2].p_pixels += dst_x / 2 + dst_y / 2 * dst_planes[2].i_pitch;
> +            break;
> +
> +        default:
> +            msg_Err(o, "Unsupported va fourcc (%4.4s)", (const char *)&va_image->format.fourcc);
> +            return VA_STATUS_ERROR_UNIMPLEMENTED;
> +    }
> +
> +    for (int i = 0; i < src->i_planes; i++) {
> +        plane_CopyPixels(&dst_planes[i], &src->p[i]);
> +    }

memcpy is murder :)

> +
> +    return VA_STATUS_SUCCESS;
> +}
> +
> +int vlc_va_PutSurface(vlc_object_t *o, VADisplay va_dpy,
> +                      VASurfaceID va_surface_id,
> +                      VAImageFormat *va_image_format, const picture_t *src,
> +                      int in_width, int in_height, int out_width, int out_height)
> +{
> +    VAImage   surface_image;
> +    VAStatus  status;
> +    uint8_t  *base;
> +    int       derived = 0;
> +
> +    /* create VAAPI image */
> +
> +    /* try DeriveImage if no scaling required */
> +    if (in_width == out_width && in_height == out_height) {
> +
> +        status = vaDeriveImage(va_dpy, va_surface_id, &surface_image);
> +        derived = (status == VA_STATUS_SUCCESS);
> +    }
> +    if (!derived) {
> +        /* fall back to PutImage */
> +        status = vaCreateImage(va_dpy, va_image_format, in_width, in_height, &surface_image);
> +        if (status != VA_STATUS_SUCCESS) {
> +            msg_Err(o, "vaCreateImage(0x%x) failed\n", va_image_format->fourcc);
> +            return status;
> +        }
> +    }
> +
> +    /* copy bits */
> +
> +    status = vaMapBuffer(va_dpy, surface_image.buf, (void **)&base);
> +    if (status != VA_STATUS_SUCCESS) {
> +        msg_Err(o, "vaMapBuffer() failed\n");
idem

> +    status = CopyPicture(o, &surface_image, base, 0, 0, src);
> +    vaUnmapBuffer(va_dpy, surface_image.buf);
> +    if (status != VA_STATUS_SUCCESS) {
> +        goto out;
> +    }
> +
> +    if (!derived) {
> +        status = vaPutImage(va_dpy, va_surface_id, surface_image.image_id,
> +                            0, 0, in_width, in_height,
> +                            0, 0, out_width, out_height);
> +        if (status != VA_STATUS_SUCCESS) {
> +            msg_Err(o, "vaPutImage(0x%x) failed\n", va_image_format->fourcc);
> +            //goto out;
> +        }
> +    }
> +
> + out:
> +    vaDestroyImage(va_dpy, surface_image.image_id);
> +    return status;
> +}
> +

> +/*****************************************************************************
> + * vlc_va.h: VAAPI helper for VLC
> + *****************************************************************************
> +typedef struct {
> +    unsigned int x;
> +    unsigned int y;
> +    unsigned int w;
> +    unsigned int h;
> +} vlc_va_rect;

subpicture_region_t ?

> +
> +typedef struct {
> +    vlc_va_rect    place; /* may be different than VAImage dimensions */
> +
> +    VASubpictureID va_subpicture_id;
> +    VAImage        va_image;
> +} vlc_va_subpicture;


> +/*****************************************************************************
> + * xcb_display.c: VAAPI XCB display
> + *****************************************************************************
> + * Copyright (C) 2016 VLC authors and VideoLAN
> + *
> + * Authors: Petri Hintukainen <phintuka at gmail.com>
> + *          Rémi Denis-Courmont
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License as published by
> + * the Free Software Foundation; either version 2.1 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program; if not, write to the Free Software Foundation,
> + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
> + *****************************************************************************/
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <stdlib.h>
> +#include <assert.h>
> +
> +#include <xcb/xcb.h>
> +
> +#include <vlc_common.h>
> +#include <vlc_plugin.h>
> +#include <vlc_vout_display.h>
> +#include <vlc_picture_pool.h>
> +#include <vlc_xlib.h>
> +
> +#include "events.h"
> +
> +#include <va/va.h>
> +#include <va/va_x11.h>
> +
> +#include "vlc_va.h"
> +
> +static int Open(vlc_object_t *);
> +static void Close(vlc_object_t *);
> +
> +vlc_module_begin()
> +    set_shortname(N_("VAAPI XCB"))
> +    set_description(N_("VA-API video output (XCB)"))
> +    set_category(CAT_VIDEO)
> +    set_subcategory(SUBCAT_VIDEO_VOUT)
> +    set_capability("vout display", 3000)

Can't we merge this with the classical XCB output?

Also, shouldn't this be a different patch?


With my kindest regards,

-- 
Jean-Baptiste Kempf
http://www.jbkempf.com/ - +33 672 704 734
Sent from my Electronic Device


More information about the vlc-devel mailing list