コード例 #1
0
ファイル: vaapiimage.cpp プロジェクト: TangXinT/libyami
ImagePtr VaapiImage::create(const DisplayPtr& display,
                           uint32_t format,
                           uint32_t width, uint32_t height)
{
    ImagePtr image;
    VAStatus status;

    if (!display || !width || !height)
        return image;

    DEBUG_FOURCC("create image with fourcc: ", format);
    const VAImageFormat *vaFormat = display->getVaFormat(format);
    if (!vaFormat) {
        ERROR("Create image failed, not supported fourcc");
        return image;
    }

    VAImagePtr vaImage(new VAImage);

    status = vaCreateImage(display->getID(), vaFormat, width, height, vaImage.get());
    if (status != VA_STATUS_SUCCESS ||
        vaImage->format.fourcc != vaFormat->fourcc) {
        ERROR("fourcc mismatch wated = 0x%x, got = 0x%x", vaFormat->fourcc, vaImage->format.fourcc);
        return image;
    }
    image.reset(new VaapiImage(display, vaImage));

    return image;
}
コード例 #2
0
ファイル: SurfaceInteropVAAPI.cpp プロジェクト: rockyhuo/QtAV
void* SurfaceInteropVAAPI::mapToHost(const VideoFormat &format, void *handle, int plane)
{
    Q_UNUSED(plane);
    int nb_fmts = vaMaxNumImageFormats(m_surface->vadisplay());
    //av_mallocz_array
    VAImageFormat *p_fmt = (VAImageFormat*)calloc(nb_fmts, sizeof(*p_fmt));
    if (!p_fmt) {
        return NULL;
    }
    if (vaQueryImageFormats(m_surface->vadisplay(), p_fmt, &nb_fmts)) {
        free(p_fmt);
        return NULL;
    }
    VAImage image;
    for (int i = 0; i < nb_fmts; i++) {
        if (p_fmt[i].fourcc == VA_FOURCC_YV12 ||
            p_fmt[i].fourcc == VA_FOURCC_IYUV ||
            p_fmt[i].fourcc == VA_FOURCC_NV12) {
            qDebug("vaCreateImage: %c%c%c%c", p_fmt[i].fourcc<<24>>24, p_fmt[i].fourcc<<16>>24, p_fmt[i].fourcc<<8>>24, p_fmt[i].fourcc>>24);
            if (vaCreateImage(m_surface->vadisplay(), &p_fmt[i], m_surface->width(), m_surface->height(), &image) != VA_STATUS_SUCCESS) {
                image.image_id = VA_INVALID_ID;
                qDebug("vaCreateImage error: %c%c%c%c", p_fmt[i].fourcc<<24>>24, p_fmt[i].fourcc<<16>>24, p_fmt[i].fourcc<<8>>24, p_fmt[i].fourcc>>24);
                continue;
            }
            /* Validate that vaGetImage works with this format */
            if (vaGetImage(m_surface->vadisplay(), m_surface->get(), 0, 0, m_surface->width(), m_surface->height(), image.image_id) != VA_STATUS_SUCCESS) {
                vaDestroyImage(m_surface->vadisplay(), image.image_id);
                qDebug("vaGetImage error: %c%c%c%c", p_fmt[i].fourcc<<24>>24, p_fmt[i].fourcc<<16>>24, p_fmt[i].fourcc<<8>>24, p_fmt[i].fourcc>>24);
                image.image_id = VA_INVALID_ID;
                continue;
            }
コード例 #3
0
ファイル: gstvaapiimage.c プロジェクト: cbetz421/gst-vaapi
static gboolean
_gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
{
    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(image);
    GstVaapiImagePrivate * const priv = image->priv;
    const VAImageFormat *va_format;
    VAStatus status;

    if (!gst_vaapi_display_has_image_format(display, format))
        return FALSE;

    va_format = gst_vaapi_image_format_get_va_format(format);
    if (!va_format)
        return FALSE;

    GST_VAAPI_DISPLAY_LOCK(display);
    status = vaCreateImage(
        GST_VAAPI_DISPLAY_VADISPLAY(display),
        (VAImageFormat *)va_format,
        priv->width,
        priv->height,
        &priv->internal_image
    );
    GST_VAAPI_DISPLAY_UNLOCK(display);
    if (status != VA_STATUS_SUCCESS ||
        priv->internal_image.format.fourcc != va_format->fourcc)
        return FALSE;

    priv->internal_format = format;
    return TRUE;
}
コード例 #4
0
ファイル: putsurface_common.c プロジェクト: Distrotech/libva
int csc_preparation ()
{
    VAStatus va_status;
    
    // 1. make sure dst fourcc is supported for vaImage
    if (!lookup_image_format(csc_dst_fourcc)) {
        test_color_conversion = 0;
        printf("VA driver doesn't support %s image, skip additional color conversion\n",  map_vafourcc_to_str(csc_dst_fourcc));
        goto cleanup;
    }

    // 2. make sure src_fourcc is supported for vaSurface
    VASurfaceAttrib surface_attribs[1], * const s_attrib = &surface_attribs[0];
    s_attrib->type = VASurfaceAttribPixelFormat;
    s_attrib->flags = VA_SURFACE_ATTRIB_SETTABLE;
    s_attrib->value.type = VAGenericValueTypeInteger;
    s_attrib->value.value.i = csc_src_fourcc;

    if (!lookup_surface_attrib(VASurfaceAttribPixelFormat, &s_attrib->value)) {
        printf("VA driver doesn't support %s surface, skip additional color conversion\n",  map_vafourcc_to_str(csc_src_fourcc));
        test_color_conversion = 0;
        goto cleanup;
    }

    // 3 create all objs required by csc
    // 3.1 vaSurface with src fourcc
    va_status = vaCreateSurfaces(
        va_dpy,
        VA_RT_FORMAT_YUV420, surface_width, surface_height,
        &surface_id[0], SURFACE_NUM,
        surface_attribs, 1
    );
    CHECK_VASTATUS(va_status,"vaCreateSurfaces");

    // 3.2 vaImage with dst fourcc
    VAImageFormat image_format;
    image_format.fourcc = csc_dst_fourcc;
    image_format.byte_order = VA_LSB_FIRST;
    image_format.bits_per_pixel = 16;
    
    va_status = vaCreateImage(va_dpy, &image_format,
                    surface_width, surface_height,
                    &csc_dst_fourcc_image);
    CHECK_VASTATUS(va_status,"vaCreateImage");
    

    // 3.3 create a temp VASurface for final rendering(vaPutSurface)
    s_attrib->value.value.i = VA_FOURCC_NV12;
    va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420, 
                                 surface_width, surface_height,
                                 &csc_render_surface, 1, 
                                 surface_attribs, 1);
    CHECK_VASTATUS(va_status,"vaCreateSurfaces");


cleanup:
    return test_color_conversion;
}
コード例 #5
0
ファイル: VAApiWriter.cpp プロジェクト: JandunCN/QMPlay2
void VAApiWriter::draw( VASurfaceID _id, int _field )
{
	if ( _id != VA_INVALID_SURFACE && _field > -1 )
	{
		if ( id != _id || _field == field )
			vaSyncSurface( VADisp, _id );
		id = _id;
		field = _field;
	}
	if ( id == VA_INVALID_SURFACE )
		return;

	bool associated = false;

	osd_mutex.lock();
	if ( !osd_list.isEmpty() )
	{
		QRect bounds;
		const qreal scaleW = ( qreal )W / outW, scaleH = ( qreal )H / outH;
		bool mustRepaint = Functions::mustRepaintOSD( osd_list, osd_checksums, &scaleW, &scaleH, &bounds );
		if ( !mustRepaint )
			mustRepaint = vaImgSize != bounds.size();
		bool canAssociate = !mustRepaint;
		if ( mustRepaint )
		{
			if ( vaImgSize != bounds.size() )
			{
				clearRGBImage();
				vaImgSize = QSize();
				if ( vaCreateImage( VADisp, rgbImgFmt, bounds.width(), bounds.height(), &vaImg ) == VA_STATUS_SUCCESS )
				{
					if ( vaCreateSubpicture( VADisp, vaImg.image_id, &vaSubpicID ) == VA_STATUS_SUCCESS )
						vaImgSize = bounds.size();
					else
						clearRGBImage();
				}
			}
			if ( vaSubpicID )
			{
				quint8 *buff;
				if ( vaMapBuffer( VADisp, vaImg.buf, ( void ** )&buff ) == VA_STATUS_SUCCESS )
				{
					QImage osdImg( buff += vaImg.offsets[ 0 ], vaImg.pitches[ 0 ] >> 2, bounds.height(), QImage::Format_ARGB32 );
					osdImg.fill( 0 );
					QPainter p( &osdImg );
					p.translate( -bounds.topLeft() );
					Functions::paintOSD( osd_list, scaleW, scaleH, p, &osd_checksums );
					vaUnmapBuffer( VADisp, vaImg.buf );
					canAssociate = true;
				}
			}
		}
コード例 #6
0
ファイル: egl_vaapi_image.cpp プロジェクト: hongbog/libyami
bool EglVaapiImage::init()
{
    if (m_inited) {
        ERROR("do not init twice");
        return false;
    }
    if (!getVaFormat(m_display, m_format))
        return false;
    VAStatus vaStatus = vaCreateImage(m_display, &m_format, m_width, m_height, &m_image);
    if (!checkVaapiStatus(vaStatus, "vaCreateImage"))
        return false;
    m_inited = true;
    return true;
}
コード例 #7
0
ファイル: VAApiWriter.cpp プロジェクト: JandunCN/QMPlay2
quint8 *VAApiWriter::getImage( VAImage &image, VASurfaceID surfaceID, VAImageFormat *img_fmt ) const
{
	if ( vaCreateImage( VADisp, img_fmt, outW, outH, &image ) == VA_STATUS_SUCCESS )
	{
		quint8 *data;
		if
		(
			vaSyncSurface( VADisp, surfaceID ) == VA_STATUS_SUCCESS &&
			vaGetImage( VADisp, surfaceID, 0, 0, outW, outH, image.image_id ) == VA_STATUS_SUCCESS &&
			vaMapBuffer( VADisp, image.buf, ( void ** )&data ) == VA_STATUS_SUCCESS
		) return data;
		vaDestroyImage( VADisp, image.image_id );
	}
	return NULL;
}
コード例 #8
0
ファイル: vaapi.c プロジェクト: repstd/modified_vlc
static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t *pi_chroma,
                           int i_width, int i_height )
{
    assert( i_width > 0 && i_height > 0 );

    /* */
    p_va->p_surface = calloc( p_va->i_surface_count, sizeof(*p_va->p_surface) );
    if( !p_va->p_surface )
        return VLC_EGENERIC;
    p_va->image.image_id = VA_INVALID_ID;
    p_va->i_context_id   = VA_INVALID_ID;

    /* Create surfaces */
    VASurfaceID pi_surface_id[p_va->i_surface_count];
    if( vaCreateSurfaces( p_va->p_display, i_width, i_height, VA_RT_FORMAT_YUV420,
                          p_va->i_surface_count, pi_surface_id ) )
    {
        for( int i = 0; i < p_va->i_surface_count; i++ )
            p_va->p_surface[i].i_id = VA_INVALID_SURFACE;
        goto error;
    }

    for( int i = 0; i < p_va->i_surface_count; i++ )
    {
        vlc_va_surface_t *p_surface = &p_va->p_surface[i];

        p_surface->i_id = pi_surface_id[i];
        p_surface->i_refcount = 0;
        p_surface->i_order = 0;
    }

    /* Create a context */
    if( vaCreateContext( p_va->p_display, p_va->i_config_id,
                         i_width, i_height, VA_PROGRESSIVE,
                         pi_surface_id, p_va->i_surface_count, &p_va->i_context_id ) )
    {
        p_va->i_context_id = VA_INVALID_ID;
        goto error;
    }

    /* Find and create a supported image chroma */
    int i_fmt_count = vaMaxNumImageFormats( p_va->p_display );
    VAImageFormat *p_fmt = calloc( i_fmt_count, sizeof(*p_fmt) );
    if( !p_fmt )
        goto error;

    if( vaQueryImageFormats( p_va->p_display, p_fmt, &i_fmt_count ) )
    {
        free( p_fmt );
        goto error;
    }

    VAImage testImage;
    if(vaDeriveImage(p_va->p_display, pi_surface_id[0], &testImage) == VA_STATUS_SUCCESS)
    {
        p_va->b_supports_derive = true;
        vaDestroyImage(p_va->p_display, testImage.image_id);
    }

    vlc_fourcc_t  i_chroma = 0;
    VAImageFormat fmt;
    for( int i = 0; i < i_fmt_count; i++ )
    {
        if( p_fmt[i].fourcc == VA_FOURCC( 'Y', 'V', '1', '2' ) ||
            p_fmt[i].fourcc == VA_FOURCC( 'I', '4', '2', '0' ) ||
            p_fmt[i].fourcc == VA_FOURCC( 'N', 'V', '1', '2' ) )
        {
            if( vaCreateImage(  p_va->p_display, &p_fmt[i], i_width, i_height, &p_va->image ) )
            {
                p_va->image.image_id = VA_INVALID_ID;
                continue;
            }
            /* Validate that vaGetImage works with this format */
            if( vaGetImage( p_va->p_display, pi_surface_id[0],
                            0, 0, i_width, i_height,
                            p_va->image.image_id) )
            {
                vaDestroyImage( p_va->p_display, p_va->image.image_id );
                p_va->image.image_id = VA_INVALID_ID;
                continue;
            }

            i_chroma = VLC_CODEC_YV12;
            fmt = p_fmt[i];
            break;
        }
    }
    free( p_fmt );
    if( !i_chroma )
        goto error;
    *pi_chroma = i_chroma;

    if(p_va->b_supports_derive)
    {
        vaDestroyImage( p_va->p_display, p_va->image.image_id );
        p_va->image.image_id = VA_INVALID_ID;
    }

    if( unlikely(CopyInitCache( &p_va->image_cache, i_width )) )
        goto error;

    /* Setup the ffmpeg hardware context */
    *pp_hw_ctx = &p_va->hw_ctx;

    memset( &p_va->hw_ctx, 0, sizeof(p_va->hw_ctx) );
    p_va->hw_ctx.display    = p_va->p_display;
    p_va->hw_ctx.config_id  = p_va->i_config_id;
    p_va->hw_ctx.context_id = p_va->i_context_id;

    /* */
    p_va->i_surface_chroma = i_chroma;
    p_va->i_surface_width = i_width;
    p_va->i_surface_height = i_height;
    return VLC_SUCCESS;

error:
    DestroySurfaces( p_va );
    return VLC_EGENERIC;
}
コード例 #9
0
ファイル: vaapicontext.cpp プロジェクト: mojie126/mythtv
bool VAAPIContext::InitImage(const void *buf)
{
    if (!buf)
        return false;
    if (!m_dispType == kVADisplayX11)
        return true;

    int num_formats = 0;
    int max_formats = vaMaxNumImageFormats(m_ctx.display);
    VAImageFormat *formats = new VAImageFormat[max_formats];

    INIT_ST;
    va_status = vaQueryImageFormats(m_ctx.display, formats, &num_formats);
    CHECK_ST;

    const vaapi_surface *surf = (vaapi_surface*)buf;
    unsigned int deriveImageFormat = 0;

    if (vaDeriveImage(m_ctx.display, surf->m_id, &m_image) == VA_STATUS_SUCCESS)
    {
        m_deriveSupport = true;
        deriveImageFormat = m_image.format.fourcc;
        vaDestroyImage(m_ctx.display, m_image.image_id);
    }

    int nv12support = -1;

    for (int i = 0; i < num_formats; i++)
    {
        if (formats[i].fourcc == VA_FOURCC_YV12 ||
            formats[i].fourcc == VA_FOURCC_IYUV ||
            formats[i].fourcc == VA_FOURCC_NV12)
        {
            if (vaCreateImage(m_ctx.display, &formats[i],
                              m_size.width(), m_size.height(), &m_image))
            {
                m_image.image_id = VA_INVALID_ID;
                continue;
            }

            if (vaGetImage(m_ctx.display, surf->m_id, 0, 0,
                           m_size.width(), m_size.height(), m_image.image_id))
            {
                vaDestroyImage(m_ctx.display, m_image.image_id);
                m_image.image_id = VA_INVALID_ID;
                continue;
            }

            if (formats[i].fourcc == VA_FOURCC_NV12)
            {
                // mark as NV12 as supported, but favor other formats first
                nv12support = i;
                vaDestroyImage(m_ctx.display, m_image.image_id);
                m_image.image_id = VA_INVALID_ID;
                continue;
            }
            break;
        }
    }

    if (m_image.image_id == VA_INVALID_ID && nv12support >= 0)
    {
        // only nv12 is supported, use that format
        if (vaCreateImage(m_ctx.display, &formats[nv12support],
                          m_size.width(), m_size.height(), &m_image))
        {
            m_image.image_id = VA_INVALID_ID;
        }
    }
    else if (m_deriveSupport && deriveImageFormat != m_image.format.fourcc)
    {
        // only use vaDerive if it's giving us a format we can handle natively
        m_deriveSupport = false;
    }

    delete [] formats;

    if (m_image.image_id == VA_INVALID_ID)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create software image.");
        return false;
    }

    LOG(VB_GENERAL, LOG_DEBUG,
        LOC + QString("InitImage: id %1, width %2 height %3 "
                      "format %4 vaDeriveSupport:%5")
        .arg(m_image.image_id).arg(m_image.width).arg(m_image.height)
        .arg(m_image.format.fourcc).arg(m_deriveSupport));

    if (m_deriveSupport)
    {
        vaDestroyImage(m_ctx.display, m_image.image_id );
        m_image.image_id = VA_INVALID_ID;
    }

    return true;
}
コード例 #10
0
ファイル: vaapi.c プロジェクト: 42TheAnswerToLife/vlc
static int Extract( vlc_va_t *va, picture_t *p_picture, uint8_t *data )
{
    vlc_va_sys_t *sys = va->sys;
    VASurfaceID surface = (VASurfaceID)(uintptr_t)data;
    VAImage image;
    int ret = VLC_EGENERIC;

#if VA_CHECK_VERSION(0,31,0)
    if (vaSyncSurface(sys->hw_ctx.display, surface))
#else
    if (vaSyncSurface(sys->hw_ctx.display, sys->hw_ctx.context_id, surface))
#endif
        return VLC_EGENERIC;

    if (!sys->do_derive || vaDeriveImage(sys->hw_ctx.display, surface, &image))
    {   /* Fallback if image derivation is not supported */
        if (vaCreateImage(sys->hw_ctx.display, &sys->format, sys->width,
                          sys->height, &image))
            return VLC_EGENERIC;
        if (vaGetImage(sys->hw_ctx.display, surface, 0, 0, sys->width,
                       sys->height, image.image_id))
            goto error;
    }

    void *p_base;
    if (vaMapBuffer(sys->hw_ctx.display, image.buf, &p_base))
        goto error;

    const unsigned i_fourcc = sys->format.fourcc;
    if( i_fourcc == VA_FOURCC_YV12 ||
        i_fourcc == VA_FOURCC_IYUV )
    {
        bool b_swap_uv = i_fourcc == VA_FOURCC_IYUV;
        uint8_t *pp_plane[3];
        size_t  pi_pitch[3];

        for( int i = 0; i < 3; i++ )
        {
            const int i_src_plane = (b_swap_uv && i != 0) ?  (3 - i) : i;
            pp_plane[i] = (uint8_t*)p_base + image.offsets[i_src_plane];
            pi_pitch[i] = image.pitches[i_src_plane];
        }
        CopyFromYv12( p_picture, pp_plane, pi_pitch, sys->width, sys->height,
                      &sys->image_cache );
    }
    else
    {
        assert( i_fourcc == VA_FOURCC_NV12 );
        uint8_t *pp_plane[2];
        size_t  pi_pitch[2];

        for( int i = 0; i < 2; i++ )
        {
            pp_plane[i] = (uint8_t*)p_base + image.offsets[i];
            pi_pitch[i] = image.pitches[i];
        }
        CopyFromNv12( p_picture, pp_plane, pi_pitch, sys->width, sys->height,
                      &sys->image_cache );
    }

    vaUnmapBuffer(sys->hw_ctx.display, image.buf);
    ret = VLC_SUCCESS;
error:
    vaDestroyImage(sys->hw_ctx.display, image.image_id);
    return ret;
}
コード例 #11
0
ファイル: vaapi.c プロジェクト: 42TheAnswerToLife/vlc
/** Finds a supported image chroma */
static int FindFormat(vlc_va_sys_t *sys)
{
    int count = vaMaxNumImageFormats(sys->hw_ctx.display);

    VAImageFormat *fmts = malloc(count * sizeof (*fmts));
    if (unlikely(fmts == NULL))
        return VLC_ENOMEM;

    if (vaQueryImageFormats(sys->hw_ctx.display, fmts, &count))
    {
        free(fmts);
        return VLC_EGENERIC;
    }

    sys->format.fourcc = 0;

    for (int i = 0; i < count; i++)
    {
        unsigned fourcc = fmts[i].fourcc;

        if (fourcc != VA_FOURCC_YV12 && fourcc != VA_FOURCC_IYUV
         && fourcc != VA_FOURCC_NV12)
            continue;

        VAImage image;

        if (vaCreateImage(sys->hw_ctx.display, &fmts[i], sys->width,
                          sys->height, &image))
            continue;

        /* Validate that vaGetImage works with this format */
        int val = vaGetImage(sys->hw_ctx.display, sys->surfaces[0], 0, 0,
                             sys->width, sys->height, image.image_id);

        vaDestroyImage(sys->hw_ctx.display, image.image_id);

        if (val != VA_STATUS_SUCCESS)
            continue;

        /* Mark NV12 as supported, but favor other formats first */
        sys->format = fmts[i];
        if (fourcc != VA_FOURCC_NV12)
            break;
    }

    free(fmts);

    if (sys->format.fourcc == 0)
        return VLC_EGENERIC; /* None of the formats work */

    VAImage image;

    /* Use vaDerive() iif it supports the best selected format */
    sys->do_derive = false;

    if (vaDeriveImage(sys->hw_ctx.display, sys->surfaces[0],
                      &image) == VA_STATUS_SUCCESS)
    {
        if (image.format.fourcc == sys->format.fourcc)
        {
            sys->do_derive = true;
            sys->format = image.format;
        }
        vaDestroyImage(sys->hw_ctx.display, image.image_id);
    }

    return VLC_SUCCESS;
}
コード例 #12
0
ファイル: vaapi.c プロジェクト: coog009/myproject
int get_image(VASurfaceID surface, Image *dst_img)
{
    VAAPIContext * const vaapi = vaapi_get_context();
    VAImage image;
    VAImageFormat *image_format = NULL;
    VAStatus status;
    Image bound_image;
    int i, is_bound_image = 0, is_derived_image = 0, error = -1;

    image.image_id = VA_INVALID_ID;
    image.buf      = VA_INVALID_ID;

    if (!image_format) {
        status = vaDeriveImage(vaapi->display, surface, &image);
        if (vaapi_check_status(status, "vaDeriveImage()")) {
            if (image.image_id != VA_INVALID_ID && image.buf != VA_INVALID_ID) {
                D(bug("using vaDeriveImage()\n"));
                is_derived_image = 1;
                image_format = &image.format;
            }
            else {
                D(bug("vaDeriveImage() returned success but VA image is invalid. Trying vaGetImage()\n"));
            }
        }
    }

    if (!image_format) {
        for (i = 0; image_formats[i] != 0; i++) {
            if (get_image_format(vaapi, image_formats[i], &image_format))
                break;
        }
    }

    if (!image_format)
        goto end;
    D(bug("selected %s image format for getimage\n",
          string_of_VAImageFormat(image_format)));

    if (!is_derived_image) {
        status = vaCreateImage(vaapi->display, image_format,
                               vaapi->picture_width, vaapi->picture_height,
                               &image);
        if (!vaapi_check_status(status, "vaCreateImage()"))
            goto end;
        D(bug("created image with id 0x%08x and buffer id 0x%08x\n",
              image.image_id, image.buf));

        VARectangle src_rect;

        src_rect.x      = 0;
        src_rect.y      = 0;
        src_rect.width  = vaapi->picture_width;
        src_rect.height = vaapi->picture_height;

        D(bug("src rect (%d,%d):%ux%u\n",
              src_rect.x, src_rect.y, src_rect.width, src_rect.height));

        status = vaGetImage(
            vaapi->display, vaapi->surface_id,
            src_rect.x, src_rect.y, src_rect.width, src_rect.height,
            image.image_id
        );
        if (!vaapi_check_status(status, "vaGetImage()")) {
            vaDestroyImage(vaapi->display, image.image_id);
            goto end;
        }
    }

    if (bind_image(&image, &bound_image) < 0)
        goto end;
    is_bound_image = 1;

    if (image_convert(dst_img, &bound_image) < 0)
        goto end;

    error = 0;
end:
    if (is_bound_image) {
        if (release_image(&image) < 0)
            error = -1;
    }

    if (image.image_id != VA_INVALID_ID) {
        status = vaDestroyImage(vaapi->display, image.image_id);
        if (!vaapi_check_status(status, "vaDestroyImage()"))
            error = -1;
    }
    return error;
}
コード例 #13
0
ファイル: hwcontext_vaapi.c プロジェクト: mark4o/FFmpeg
static int vaapi_map_frame(AVHWFramesContext *hwfc,
                           AVFrame *dst, const AVFrame *src, int flags)
{
    AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
    VAAPIFramesContext *ctx = hwfc->internal->priv;
    VASurfaceID surface_id;
    VAImageFormat *image_format;
    VAAPISurfaceMap *map;
    VAStatus vas;
    void *address = NULL;
    int err, i;

    surface_id = (VASurfaceID)(uintptr_t)src->data[3];
    av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id);

    if (!ctx->derive_works && (flags & VAAPI_MAP_DIRECT)) {
        // Requested direct mapping but it is not possible.
        return AVERROR(EINVAL);
    }
    if (dst->format == AV_PIX_FMT_NONE)
        dst->format = hwfc->sw_format;
    if (dst->format != hwfc->sw_format && (flags & VAAPI_MAP_DIRECT)) {
        // Requested direct mapping but the formats do not match.
        return AVERROR(EINVAL);
    }

    err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format);
    if (err < 0) {
        // Requested format is not a valid output format.
        return AVERROR(EINVAL);
    }

    map = av_malloc(sizeof(VAAPISurfaceMap));
    if (!map)
        return AVERROR(ENOMEM);

    map->source         = src;
    map->flags          = flags;
    map->image.image_id = VA_INVALID_ID;

    vas = vaSyncSurface(hwctx->display, surface_id);
    if (vas != VA_STATUS_SUCCESS) {
        av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
               "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
        err = AVERROR(EIO);
        goto fail;
    }

    // The memory which we map using derive need not be connected to the CPU
    // in a way conducive to fast access.  On Gen7-Gen9 Intel graphics, the
    // memory is mappable but not cached, so normal memcpy()-like access is
    // very slow to read it (but writing is ok).  It is possible to read much
    // faster with a copy routine which is aware of the limitation, but we
    // assume for now that the user is not aware of that and would therefore
    // prefer not to be given direct-mapped memory if they request read access.
    if (ctx->derive_works &&
        ((flags & VAAPI_MAP_DIRECT) || !(flags & VAAPI_MAP_READ))) {
        vas = vaDeriveImage(hwctx->display, surface_id, &map->image);
        if (vas != VA_STATUS_SUCCESS) {
            av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
                   "surface %#x: %d (%s).\n",
                   surface_id, vas, vaErrorStr(vas));
            err = AVERROR(EIO);
            goto fail;
        }
        if (map->image.format.fourcc != image_format->fourcc) {
            av_log(hwfc, AV_LOG_ERROR, "Derive image of surface %#x "
                   "is in wrong format: expected %#08x, got %#08x.\n",
                   surface_id, image_format->fourcc, map->image.format.fourcc);
            err = AVERROR(EIO);
            goto fail;
        }
        map->flags |= VAAPI_MAP_DIRECT;
    } else {
        vas = vaCreateImage(hwctx->display, image_format,
                            hwfc->width, hwfc->height, &map->image);
        if (vas != VA_STATUS_SUCCESS) {
            av_log(hwfc, AV_LOG_ERROR, "Failed to create image for "
                   "surface %#x: %d (%s).\n",
                   surface_id, vas, vaErrorStr(vas));
            err = AVERROR(EIO);
            goto fail;
        }
        if (flags & VAAPI_MAP_READ) {
            vas = vaGetImage(hwctx->display, surface_id, 0, 0,
                             hwfc->width, hwfc->height, map->image.image_id);
            if (vas != VA_STATUS_SUCCESS) {
                av_log(hwfc, AV_LOG_ERROR, "Failed to read image from "
                       "surface %#x: %d (%s).\n",
                       surface_id, vas, vaErrorStr(vas));
                err = AVERROR(EIO);
                goto fail;
            }
        }
    }

    vas = vaMapBuffer(hwctx->display, map->image.buf, &address);
    if (vas != VA_STATUS_SUCCESS) {
        av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface "
               "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
        err = AVERROR(EIO);
        goto fail;
    }

    dst->width  = src->width;
    dst->height = src->height;

    for (i = 0; i < map->image.num_planes; i++) {
        dst->data[i] = (uint8_t*)address + map->image.offsets[i];
        dst->linesize[i] = map->image.pitches[i];
    }
    if (
#ifdef VA_FOURCC_YV16
        map->image.format.fourcc == VA_FOURCC_YV16 ||
#endif
        map->image.format.fourcc == VA_FOURCC_YV12) {
        // Chroma planes are YVU rather than YUV, so swap them.
        FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
    }