int ff_vaapi_decode_init(AVCodecContext *avctx) { VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; VAStatus vas; int err; ctx->va_config = VA_INVALID_ID; ctx->va_context = VA_INVALID_ID; #if FF_API_STRUCT_VAAPI_CONTEXT if (avctx->hwaccel_context) { av_log(avctx, AV_LOG_WARNING, "Using deprecated struct " "vaapi_context in decode.\n"); ctx->have_old_context = 1; ctx->old_context = avctx->hwaccel_context; // Really we only want the VAAPI device context, but this // allocates a whole generic device context because we don't // have any other way to determine how big it should be. ctx->device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI); if (!ctx->device_ref) { err = AVERROR(ENOMEM); goto fail; } ctx->device = (AVHWDeviceContext*)ctx->device_ref->data; ctx->hwctx = ctx->device->hwctx; ctx->hwctx->display = ctx->old_context->display; // The old VAAPI decode setup assumed this quirk was always // present, so set it here to avoid the behaviour changing. ctx->hwctx->driver_quirks = AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS; } #endif #if FF_API_STRUCT_VAAPI_CONTEXT if (ctx->have_old_context) { ctx->va_config = ctx->old_context->config_id; ctx->va_context = ctx->old_context->context_id; av_log(avctx, AV_LOG_DEBUG, "Using user-supplied decoder " "context: %#x/%#x.\n", ctx->va_config, ctx->va_context); } else { #endif err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VAAPI); if (err < 0) goto fail; ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; ctx->hwfc = ctx->frames->hwctx; ctx->device = ctx->frames->device_ctx; ctx->hwctx = ctx->device->hwctx; err = vaapi_decode_make_config(avctx, ctx->frames->device_ref, &ctx->va_config, avctx->hw_frames_ctx); if (err) goto fail; vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, avctx->coded_width, avctx->coded_height, VA_PROGRESSIVE, ctx->hwfc->surface_ids, ctx->hwfc->nb_surfaces, &ctx->va_context); if (vas != VA_STATUS_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to create decode " "context: %d (%s).\n", vas, vaErrorStr(vas)); err = AVERROR(EIO); goto fail; } av_log(avctx, AV_LOG_DEBUG, "Decode context initialised: " "%#x/%#x.\n", ctx->va_config, ctx->va_context); #if FF_API_STRUCT_VAAPI_CONTEXT } #endif return 0; fail: ff_vaapi_decode_uninit(avctx); return err; }
int ff_nvdec_decode_init(AVCodecContext *avctx) { NVDECContext *ctx = avctx->internal->hwaccel_priv_data; NVDECFramePool *pool; AVHWFramesContext *frames_ctx; const AVPixFmtDescriptor *sw_desc; CUVIDDECODECREATEINFO params = { 0 }; int cuvid_codec_type, cuvid_chroma_format; int ret = 0; sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); if (!sw_desc) return AVERROR_BUG; cuvid_codec_type = map_avcodec_id(avctx->codec_id); if (cuvid_codec_type < 0) { av_log(avctx, AV_LOG_ERROR, "Unsupported codec ID\n"); return AVERROR_BUG; } cuvid_chroma_format = map_chroma_format(avctx->sw_pix_fmt); if (cuvid_chroma_format < 0) { av_log(avctx, AV_LOG_ERROR, "Unsupported chroma format\n"); return AVERROR(ENOSYS); } if (!avctx->hw_frames_ctx) { ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_CUDA); if (ret < 0) return ret; } frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; params.ulWidth = avctx->coded_width; params.ulHeight = avctx->coded_height; params.ulTargetWidth = avctx->coded_width; params.ulTargetHeight = avctx->coded_height; params.bitDepthMinus8 = sw_desc->comp[0].depth - 8; params.OutputFormat = params.bitDepthMinus8 ? cudaVideoSurfaceFormat_P016 : cudaVideoSurfaceFormat_NV12; params.CodecType = cuvid_codec_type; params.ChromaFormat = cuvid_chroma_format; params.ulNumDecodeSurfaces = frames_ctx->initial_pool_size; params.ulNumOutputSurfaces = frames_ctx->initial_pool_size; ret = nvdec_decoder_create(&ctx->decoder_ref, frames_ctx->device_ref, ¶ms, avctx); if (ret < 0) { if (params.ulNumDecodeSurfaces > 32) { av_log(avctx, AV_LOG_WARNING, "Using more than 32 (%d) decode surfaces might cause nvdec to fail.\n", (int)params.ulNumDecodeSurfaces); av_log(avctx, AV_LOG_WARNING, "Try lowering the amount of threads. Using %d right now.\n", avctx->thread_count); } return ret; } pool = av_mallocz(sizeof(*pool)); if (!pool) { ret = AVERROR(ENOMEM); goto fail; } pool->dpb_size = frames_ctx->initial_pool_size; ctx->decoder_pool = av_buffer_pool_init2(sizeof(int), pool, nvdec_decoder_frame_alloc, av_free); if (!ctx->decoder_pool) { ret = AVERROR(ENOMEM); goto fail; } return 0; fail: ff_nvdec_decode_uninit(avctx); return ret; }
int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, int level) { VDPAUHWContext *hwctx = avctx->hwaccel_context; VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data; VdpVideoSurfaceQueryCapabilities *surface_query_caps; VdpDecoderQueryCapabilities *decoder_query_caps; VdpDecoderCreate *create; VdpGetInformationString *info; const char *info_string; void *func; VdpStatus status; VdpBool supported; uint32_t max_level, max_mb, max_width, max_height; VdpChromaType type; uint32_t width; uint32_t height; int ret; vdctx->width = UINT32_MAX; vdctx->height = UINT32_MAX; if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height)) return AVERROR(ENOSYS); if (hwctx) { hwctx->reset = 0; if (hwctx->context.decoder != VDP_INVALID_HANDLE) { vdctx->decoder = hwctx->context.decoder; vdctx->render = hwctx->context.render; vdctx->device = VDP_INVALID_HANDLE; return 0; /* Decoder created by user */ } vdctx->device = hwctx->device; vdctx->get_proc_address = hwctx->get_proc_address; if (hwctx->flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) level = 0; if (!(hwctx->flags & AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH) && type != VDP_CHROMA_TYPE_420) return AVERROR(ENOSYS); } else { AVHWFramesContext *frames_ctx; AVVDPAUDeviceContext *dev_ctx; ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VDPAU); if (ret < 0) return ret; frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; dev_ctx = frames_ctx->device_ctx->hwctx; vdctx->device = dev_ctx->device; vdctx->get_proc_address = dev_ctx->get_proc_address; if (avctx->hwaccel_flags & AV_HWACCEL_FLAG_IGNORE_LEVEL) level = 0; } if (level < 0) return AVERROR(ENOTSUP); status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_GET_INFORMATION_STRING, &func); if (status != VDP_STATUS_OK) return vdpau_error(status); else info = func; status = info(&info_string); if (status != VDP_STATUS_OK) return vdpau_error(status); if (avctx->codec_id == AV_CODEC_ID_HEVC && strncmp(info_string, "NVIDIA ", 7) == 0 && !(avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH)) { int driver_version = 0; sscanf(info_string, "NVIDIA VDPAU Driver Shared Library %d", &driver_version); if (driver_version < 410) { av_log(avctx, AV_LOG_VERBOSE, "HEVC with NVIDIA VDPAU drivers is buggy, skipping.\n"); return AVERROR(ENOTSUP); } } status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, &func); if (status != VDP_STATUS_OK) return vdpau_error(status); else surface_query_caps = func; status = surface_query_caps(vdctx->device, type, &supported, &max_width, &max_height); if (status != VDP_STATUS_OK) return vdpau_error(status); if (supported != VDP_TRUE || max_width < width || max_height < height) return AVERROR(ENOTSUP); status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, &func); if (status != VDP_STATUS_OK) return vdpau_error(status); else decoder_query_caps = func; status = decoder_query_caps(vdctx->device, profile, &supported, &max_level, &max_mb, &max_width, &max_height); #ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE if ((status != VDP_STATUS_OK || supported != VDP_TRUE) && profile == VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE) { profile = VDP_DECODER_PROFILE_H264_MAIN; status = decoder_query_caps(vdctx->device, profile, &supported, &max_level, &max_mb, &max_width, &max_height); } #endif if (status != VDP_STATUS_OK) return vdpau_error(status); if (supported != VDP_TRUE || max_level < level || max_width < width || max_height < height) return AVERROR(ENOTSUP); status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_CREATE, &func); if (status != VDP_STATUS_OK) return vdpau_error(status); else create = func; status = vdctx->get_proc_address(vdctx->device, VDP_FUNC_ID_DECODER_RENDER, &func); if (status != VDP_STATUS_OK) return vdpau_error(status); else vdctx->render = func; status = create(vdctx->device, profile, width, height, avctx->refs, &vdctx->decoder); if (status == VDP_STATUS_OK) { vdctx->width = avctx->coded_width; vdctx->height = avctx->coded_height; } return vdpau_error(status); }