void test() { VAEntrypoint entrypoints[5]; int num_entrypoints,slice_entrypoint; VAConfigAttrib attrib[2]; VAConfigID config_id; unsigned int fourcc, luma_stride, chroma_u_stride, chroma_v_stride, luma_offset, chroma_u_offset; unsigned int chroma_v_offset, buffer_name; unsigned int *p_buffer; int i, ret; char c; int frame_width=640, frame_height=480; VASurfaceID surface_id; VAImage image_id; unsigned char *usrbuf; usrbuf = (unsigned char*)malloc(frame_width * frame_height * 2); ASSERT ( usrbuf != NULL); VASurfaceAttribExternalBuffers vaSurfaceExternBuf; VASurfaceAttrib attrib_list[2]; va_status = vaQueryConfigEntrypoints(va_dpy, VAProfileH264Baseline, entrypoints, &num_entrypoints); ASSERT( VA_STATUS_SUCCESS == va_status ); for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) { if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice) break; } if (slice_entrypoint == num_entrypoints) { /* not find Slice entry point */ status("VAEntrypointEncSlice doesn't support, exit.\n"); ASSERT(0); } /* find out the format for the render target, and rate control mode */ attrib[0].type = VAConfigAttribRTFormat; attrib[1].type = VAConfigAttribRateControl; va_status = vaGetConfigAttributes(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice, &attrib[0], 2); ASSERT( VA_STATUS_SUCCESS == va_status ); if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) { /* not find desired YUV420 RT format */ status("VA_RT_FORMAT_YUV420 doesn't support, exit\n"); ASSERT(0); } if ((attrib[1].value & VA_RC_VBR) == 0) { /* Can't find matched RC mode */ status("VBR mode doesn't found, exit\n"); ASSERT(0); } attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */ attrib[1].value = VA_RC_VBR; /* set to desired RC mode */ va_status = vaCreateConfig(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice, &attrib[0], 2, &config_id); ASSERT( VA_STATUS_SUCCESS == va_status ); attrib_list[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor; attrib_list[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType; va_status = vaGetSurfaceAttributes(va_dpy, config_id, attrib_list, 2); ASSERT( VA_STATUS_SUCCESS == va_status ); if (attrib_list[0].flags != VA_SURFACE_ATTRIB_NOT_SUPPORTED) { status("supported memory type:\n"); if (attrib_list[0].value.value.i & VA_SURFACE_ATTRIB_MEM_TYPE_VA) status("\tVA_SURFACE_ATTRIB_MEM_TYPE_VA\n"); if (attrib_list[0].value.value.i & VA_SURFACE_ATTRIB_MEM_TYPE_V4L2) status("\tVA_SURFACE_ATTRIB_MEM_TYPE_V4L2\n"); if (attrib_list[0].value.value.i & VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR) status("\tVA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR\n"); if (attrib_list[0].value.value.i & VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC) status("\tVA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC\n"); if (attrib_list[0].value.value.i & VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_ION) status("\tVA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_ION\n"); if (attrib_list[0].value.value.i & VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM) status("\tVA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM\n"); } if ((attrib_list[1].flags != VA_SURFACE_ATTRIB_NOT_SUPPORTED) && (attrib_list[0].value.value.i & VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR)) { status("vaCreateSurfaces from external usr pointer\n"); vaSurfaceExternBuf.buffers = (unsigned long*)malloc(sizeof(unsigned int)); vaSurfaceExternBuf.buffers[0] = usrbuf; vaSurfaceExternBuf.num_buffers = 1; vaSurfaceExternBuf.width = frame_width; vaSurfaceExternBuf.height = frame_height; vaSurfaceExternBuf.pitches[0] = vaSurfaceExternBuf.pitches[1] = vaSurfaceExternBuf.pitches[2] = frame_width; //vaSurfaceExternBuf.flags = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC; vaSurfaceExternBuf.pixel_format = VA_FOURCC_NV12; //vaSurfaceExternBuf.pitches[0] = attribute_tpi->luma_stride; attrib_list[1].flags = VA_SURFACE_ATTRIB_SETTABLE; attrib_list[1].value.type = VAGenericValueTypePointer; attrib_list[1].value.value.p = (void *)&vaSurfaceExternBuf; attrib_list[0].flags = VA_SURFACE_ATTRIB_SETTABLE; attrib_list[0].value.type = VAGenericValueTypeInteger; attrib_list[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR; va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420, frame_width, frame_height, &surface_id, 1, attrib_list, 2); ASSERT( VA_STATUS_SUCCESS == va_status ); va_status = vaDeriveImage(va_dpy, surface_id, &image_id); ASSERT( VA_STATUS_SUCCESS == va_status ); va_status = vaMapBuffer(va_dpy, image_id.buf, (void**)&p_buffer); ASSERT( VA_STATUS_SUCCESS == va_status ); memset(p_buffer, 0x80, image_id.width * image_id.height); va_status = vaUnmapBuffer(va_dpy, image_id.buf); ASSERT( VA_STATUS_SUCCESS == va_status ); va_status = vaDestroyImage(va_dpy, image_id.image_id); ASSERT( VA_STATUS_SUCCESS == va_status ); va_status = vaDestroySurfaces(va_dpy, &surface_id, 1); ASSERT( VA_STATUS_SUCCESS == va_status ); } va_status = vaDestroyConfig(va_dpy, config_id); ASSERT( VA_STATUS_SUCCESS == va_status ); free(usrbuf); }
VaApi::VaApi() { init = true; auto xdpy = QX11Info::display(); VADisplay display = m_display = vaGetDisplayGLX(xdpy); if (!check(display ? VA_STATUS_SUCCESS : VA_STATUS_ERROR_UNIMPLEMENTED, "Cannot create VADisplay.")) return; int major, minor; if (!check(vaInitialize(m_display, &major, &minor), "Cannot initialize VA-API.")) return; auto size = vaMaxNumProfiles(display); m_profiles.resize(size); if (!check(vaQueryConfigProfiles(display, m_profiles.data(), &size), "No available profiles.")) return; m_profiles.resize(size); for (auto profile : m_profiles) { int size = vaMaxNumEntrypoints(display); QVector<VAEntrypoint> entries(size); if (!isSuccess(vaQueryConfigEntrypoints(display, profile, entries.data(), &size))) continue; entries.resize(size); m_entries.insert(profile, entries); } initCodecs(); #ifdef USE_VAVPP initFilters(); #endif _Debug("VA-API is initialized."); ok = true; }
static int has_entrypoint(VAAPIContext *vaapi, VAProfile profile, VAEntrypoint entrypoint) { VAStatus status; int i; if (!vaapi->entrypoints || vaapi->n_entrypoints == 0) { vaapi->entrypoints = calloc(vaMaxNumEntrypoints(vaapi->display), sizeof(vaapi->entrypoints[0])); status = vaQueryConfigEntrypoints(vaapi->display, profile, vaapi->entrypoints, &vaapi->n_entrypoints); if (!vaapi_check_status(status, "vaQueryConfigEntrypoints()")) return 0; D(bug("%d entrypoints available for %s\n", vaapi->n_entrypoints, string_of_VAProfile(profile))); for (i = 0; i < vaapi->n_entrypoints; i++) D(bug(" %s\n", string_of_VAEntrypoint(vaapi->entrypoints[i]))); } for (i = 0; i < vaapi->n_entrypoints; i++) { if (vaapi->entrypoints[i] == entrypoint) return 1; } return 0; }
static bool IsEntrypointAvailable(VADisplay dpy, VAProfile i_profile, VAEntrypoint entrypoint) { VAEntrypoint * entrypoints; int num_entrypoints = vaMaxNumEntrypoints(dpy); bool ret = false; if (num_entrypoints <= 0) return false; entrypoints = vlc_alloc(num_entrypoints, sizeof(VAEntrypoint)); if (!entrypoints) return false; VAStatus status = vaQueryConfigEntrypoints(dpy, i_profile, entrypoints, &num_entrypoints); if (status != VA_STATUS_SUCCESS) goto error; for (int i = 0; i < num_entrypoints; ++i) if (entrypoint == entrypoints[i]) { ret = true; break; } error: free(entrypoints); return ret; }
static void checkIfAvailableYUV420() { VAEntrypoint entrypoints[5]; int num_entrypoints,vld_entrypoint; VAConfigAttrib attrib; VAStatus status; status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints, &num_entrypoints); CHECK_VASTATUS(status, "vaQueryConfigEntrypoints"); for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; ++vld_entrypoint) { if (entrypoints[vld_entrypoint] == VAEntrypointVLD) break; } if (vld_entrypoint == num_entrypoints) throw std::runtime_error("Failed to find VLD entry point"); attrib.type = VAConfigAttribRTFormat; vaGetConfigAttributes(va::display, VAProfileMPEG2Main, VAEntrypointVLD, &attrib, 1); if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) throw std::runtime_error("Desired YUV420 RT format not found"); }
bool VAAPIContext::InitProfiles(void) { if (!(codec_is_vaapi_hw(m_codec)) || !m_ctx.display) return false; MythXLocker locker(m_display->m_x_disp); int max_profiles, max_entrypoints; VAProfile profile_wanted = preferredProfile(m_codec); if (profile_wanted == VAProfileMPEG2Simple) { LOG(VB_PLAYBACK, LOG_ERR, LOC + "Codec is not supported."); return false; } VAProfile profile_found = VAProfileMPEG2Simple; // unsupported value VAEntrypoint entry_found = VAEntrypointEncSlice; // unsupported value max_profiles = vaMaxNumProfiles(m_ctx.display); max_entrypoints = vaMaxNumEntrypoints(m_ctx.display); VAProfile *profiles = new VAProfile[max_profiles]; VAEntrypoint *entries = new VAEntrypoint[max_entrypoints]; static bool debugged = false; if (profiles && entries) { INIT_ST; int act_profiles, act_entries; va_status = vaQueryConfigProfiles(m_ctx.display, profiles, &act_profiles); CHECK_ST; if (ok && act_profiles > 0) { for (int i = 0; i < act_profiles; i++) { va_status = vaQueryConfigEntrypoints(m_ctx.display, profiles[i], entries, &act_entries); if (va_status == VA_STATUS_SUCCESS && act_entries > 0) { if (profiles[i] == profile_wanted) { profile_found = profile_wanted; for (int j = 0; j < act_entries; j++) if (entries[j] < entry_found) entry_found = entries[j]; } if (!debugged) { QString entrylist = "Entrypoints: "; for (int j = 0; j < act_entries; j++) entrylist += entryToString(entries[j]); LOG(VB_GENERAL, LOG_INFO, LOC + QString("Profile: %1 %2") .arg(profileToString(profiles[i])) .arg(entrylist)); } } } } debugged = true; } delete [] profiles; delete [] entries; LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Desired profile for '%1': %2") .arg(toString(m_codec)).arg(profileToString(profile_wanted))); LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Found profile %1 with entry %2") .arg(profileToString(profile_found)).arg(entryToString(entry_found))); if (profile_wanted != profile_found) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find supported profile."); return false; } if (entry_found > VAEntrypointVLD) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find suitable entry point."); return false; } m_vaProfile = profile_wanted; m_vaEntrypoint = entry_found; if (VAEntrypointVLD == m_vaEntrypoint) m_pix_fmt = PIX_FMT_VAAPI_VLD; return true; }
static void h264_init_decoder(int width, int height) { VAStatus va_status; if (va_context_id) { rfbClientLog("%s: va_dpy already initialized\n", __FUNCTION__); } if (va_dpy != NULL) { rfbClientLog("%s: Re-initializing H.264 decoder\n", __FUNCTION__); } else { rfbClientLog("%s: initializing H.264 decoder\n", __FUNCTION__); /* Attach VA display to local X display */ Display *win_display = (Display *)XOpenDisplay(":0.0"); if (win_display == NULL) { rfbClientErr("Can't connect to local display\n"); exit(-1); } int major_ver, minor_ver; va_dpy = vaGetDisplay(win_display); va_status = vaInitialize(va_dpy, &major_ver, &minor_ver); CHECK_VASTATUS(va_status, "vaInitialize"); rfbClientLog("%s: libva version %d.%d found\n", __FUNCTION__, major_ver, minor_ver); } /* Check for VLD entrypoint */ int num_entrypoints; VAEntrypoint entrypoints[5]; int vld_entrypoint_found = 0; /* Change VAProfileH264High if needed */ VAProfile profile = VAProfileH264High; va_status = vaQueryConfigEntrypoints(va_dpy, profile, entrypoints, &num_entrypoints); CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints"); int i; for (i = 0; i < num_entrypoints; ++i) { if (entrypoints[i] == VAEntrypointVLD) { vld_entrypoint_found = 1; break; } } if (vld_entrypoint_found == 0) { rfbClientErr("VLD entrypoint not found\n"); exit(1); } /* Create configuration for the decode pipeline */ VAConfigAttrib attrib; attrib.type = VAConfigAttribRTFormat; va_status = vaCreateConfig(va_dpy, profile, VAEntrypointVLD, &attrib, 1, &va_config_id); CHECK_VASTATUS(va_status, "vaCreateConfig"); /* Create VA surfaces */ for (i = 0; i < SURFACE_NUM; ++i) { va_surface_id[i] = VA_INVALID_ID; va_pic_param_buf_id[i] = VA_INVALID_ID; va_mat_param_buf_id[i] = VA_INVALID_ID; va_sp_param_buf_id[i] = VA_INVALID_ID; va_d_param_buf_id[i] = VA_INVALID_ID; } va_status = vaCreateSurfaces(va_dpy, width, height, VA_RT_FORMAT_YUV420, SURFACE_NUM, &va_surface_id[0]); CHECK_VASTATUS(va_status, "vaCreateSurfaces"); for (i = 0; i < SURFACE_NUM; ++i) { DebugLog(("%s: va_surface_id[%d] = %p\n", __FUNCTION__, i, va_surface_id[i])); } /* Create VA context */ va_status = vaCreateContext(va_dpy, va_config_id, width, height, 0/*VA_PROGRESSIVE*/, &va_surface_id[0], SURFACE_NUM, &va_context_id); CHECK_VASTATUS(va_status, "vaCreateContext"); DebugLog(("%s: VA context created (id: %d)\n", __FUNCTION__, va_context_id)); /* Instantiate decode pipeline */ va_status = vaBeginPicture(va_dpy, va_context_id, va_surface_id[0]); CHECK_VASTATUS(va_status, "vaBeginPicture"); rfbClientLog("%s: H.264 decoder initialized\n", __FUNCTION__); }
static av_cold int vaapi_encode_check_config(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; VAStatus vas; int i, n, err; VAProfile *profiles = NULL; VAEntrypoint *entrypoints = NULL; VAConfigAttrib attr[] = { { VAConfigAttribRateControl }, { VAConfigAttribEncMaxRefFrames }, }; n = vaMaxNumProfiles(ctx->hwctx->display); profiles = av_malloc_array(n, sizeof(VAProfile)); if (!profiles) { err = AVERROR(ENOMEM); goto fail; } vas = vaQueryConfigProfiles(ctx->hwctx->display, profiles, &n); if (vas != VA_STATUS_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n", vas, vaErrorStr(vas)); err = AVERROR(ENOSYS); goto fail; } for (i = 0; i < n; i++) { if (profiles[i] == ctx->va_profile) break; } if (i >= n) { av_log(ctx, AV_LOG_ERROR, "Encoding profile not found (%d).\n", ctx->va_profile); err = AVERROR(ENOSYS); goto fail; } n = vaMaxNumEntrypoints(ctx->hwctx->display); entrypoints = av_malloc_array(n, sizeof(VAEntrypoint)); if (!entrypoints) { err = AVERROR(ENOMEM); goto fail; } vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile, entrypoints, &n); if (vas != VA_STATUS_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to query entrypoints for " "profile %u: %d (%s).\n", ctx->va_profile, vas, vaErrorStr(vas)); err = AVERROR(ENOSYS); goto fail; } for (i = 0; i < n; i++) { if (entrypoints[i] == ctx->va_entrypoint) break; } if (i >= n) { av_log(ctx, AV_LOG_ERROR, "Encoding entrypoint not found " "(%d / %d).\n", ctx->va_profile, ctx->va_entrypoint); err = AVERROR(ENOSYS); goto fail; } vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, ctx->va_entrypoint, attr, FF_ARRAY_ELEMS(attr)); if (vas != VA_STATUS_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to fetch config " "attributes: %d (%s).\n", vas, vaErrorStr(vas)); return AVERROR(EINVAL); } for (i = 0; i < FF_ARRAY_ELEMS(attr); i++) { if (attr[i].value == VA_ATTRIB_NOT_SUPPORTED) { // Unfortunately we have to treat this as "don't know" and hope // for the best, because the Intel MJPEG encoder returns this // for all the interesting attributes. continue; } switch (attr[i].type) { case VAConfigAttribRateControl: if (!(ctx->va_rc_mode & attr[i].value)) { av_log(avctx, AV_LOG_ERROR, "Rate control mode is not " "supported: %x\n", attr[i].value); err = AVERROR(EINVAL); goto fail; } break; case VAConfigAttribEncMaxRefFrames: { unsigned int ref_l0 = attr[i].value & 0xffff; unsigned int ref_l1 = (attr[i].value >> 16) & 0xffff; if (avctx->gop_size > 1 && ref_l0 < 1) { av_log(avctx, AV_LOG_ERROR, "P frames are not " "supported (%x).\n", attr[i].value); err = AVERROR(EINVAL); goto fail; } if (avctx->max_b_frames > 0 && ref_l1 < 1) { av_log(avctx, AV_LOG_ERROR, "B frames are not " "supported (%x).\n", attr[i].value); err = AVERROR(EINVAL); goto fail; } } break; } } err = 0; fail: av_freep(&profiles); av_freep(&entrypoints); return err; }