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; }
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; }
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; }
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; }
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; } } }
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; }
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; }
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; }
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; }
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; }
/** 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; }
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; }
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]); }