int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags) { AVBufferRef *device_ref = NULL; AVHWDeviceContext *device_ctx; int ret = 0; device_ref = av_hwdevice_ctx_alloc(type); if (!device_ref) { ret = AVERROR(ENOMEM); goto fail; } device_ctx = (AVHWDeviceContext*)device_ref->data; if (!device_ctx->internal->hw_type->device_create) { ret = AVERROR(ENOSYS); goto fail; } ret = device_ctx->internal->hw_type->device_create(device_ctx, device, opts, flags); if (ret < 0) goto fail; ret = av_hwdevice_ctx_init(device_ref); if (ret < 0) goto fail; *pdevice_ref = device_ref; return 0; fail: av_buffer_unref(&device_ref); *pdevice_ref = NULL; return ret; }
/** \fn pre-open */ bool ADM_ffVAEncHEVC::configureContext(void) { ADM_info("Configuring context for VAAPI encoder\n"); ADM_info("Our display: %#x\n",admLibVA::getDisplay()); _context->bit_rate=VaEncHevcSettings.bitrate*1000; _context->rc_max_rate=VaEncHevcSettings.max_bitrate*1000; _context->max_b_frames=VaEncHevcSettings.bframes; _context->pix_fmt =AV_PIX_FMT_VAAPI; #define CLEARTEXT(x) char buf[AV_ERROR_MAX_STRING_SIZE]={0}; av_make_error_string(buf,AV_ERROR_MAX_STRING_SIZE,x); hwDeviceCtx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI); if(!hwDeviceCtx) { ADM_error("Cannot allocate hw device context.\n"); return false; } AVHWDeviceContext *hwctx = (AVHWDeviceContext *)hwDeviceCtx->data; AVVAAPIDeviceContext *vactx = (AVVAAPIDeviceContext *)hwctx->hwctx; vactx->display = admLibVA::getDisplay(); int err = av_hwdevice_ctx_init(hwDeviceCtx); if(err) { CLEARTEXT(err) ADM_warning("Cannot initialize VAAPI hwdevice (%d, %s)\n",err,buf); return false; } AVBufferRef *hwFramesRef = NULL; AVHWFramesContext *hwFramesCtx = NULL; hwFramesRef = av_hwframe_ctx_alloc(hwDeviceCtx); if(!hwFramesRef) { ADM_error("Cannot create VAAPI frame context.\n"); return false; } hwFramesCtx=(AVHWFramesContext*)(hwFramesRef->data); hwFramesCtx->format=AV_PIX_FMT_VAAPI; hwFramesCtx->sw_format=AV_PIX_FMT_NV12; hwFramesCtx->width=source->getInfo()->width; hwFramesCtx->height=source->getInfo()->height; hwFramesCtx->initial_pool_size=20; err = av_hwframe_ctx_init(hwFramesRef); if(err<0) { CLEARTEXT(err) ADM_error("Cannot initialize VAAPI frame context (%d, %s)\n",err,buf); av_buffer_unref(&hwFramesRef); return false; } _context->hw_frames_ctx = av_buffer_ref(hwFramesRef); if(!_context->hw_frames_ctx) { ADM_error("hw_frames_ctx is NULL!\n"); return false; } av_buffer_unref(&hwFramesRef); return true; }
static int vdpau_alloc(AVCodecContext *s) { int loglevel = AV_LOG_ERROR; VDPAUContext *ctx; const char *display, *vendor; VdpStatus err; int ret; VdpDevice device; VdpGetProcAddress *get_proc_address; VdpGetInformationString *get_information_string; VDPAUHWDevicePriv *device_priv = NULL; AVHWDeviceContext *device_ctx; AVVDPAUDeviceContext *device_hwctx; AVHWFramesContext *frames_ctx; ctx = av_mallocz(sizeof(*ctx)); if (!ctx) return AVERROR(ENOMEM); device_priv = av_mallocz(sizeof(*device_priv)); if (!device_priv) { av_freep(&ctx); goto fail; } device_priv->dpy = XOpenDisplay(":0"); if (!device_priv->dpy) { av_log(NULL, loglevel, "Cannot open the X11 display %s.\n", XDisplayName(":0")); goto fail; } display = XDisplayString(device_priv->dpy); err = vdp_device_create_x11(device_priv->dpy, XDefaultScreen(device_priv->dpy), &device, &get_proc_address); if (err != VDP_STATUS_OK) { av_log(NULL, loglevel, "VDPAU device creation on X11 display %s failed.\n", display); goto fail; } #define GET_CALLBACK(id, result) \ do { \ void *tmp; \ err = get_proc_address(device, id, &tmp); \ if (err != VDP_STATUS_OK) { \ av_log(NULL, loglevel, "Error getting the " #id " callback.\n"); \ goto fail; \ } \ result = tmp; \ } while (0) GET_CALLBACK(VDP_FUNC_ID_GET_INFORMATION_STRING, get_information_string); GET_CALLBACK(VDP_FUNC_ID_DEVICE_DESTROY, device_priv->device_destroy); device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VDPAU); if (!device_ref) goto fail; device_ctx = (AVHWDeviceContext*)device_ref->data; device_hwctx = device_ctx->hwctx; device_ctx->user_opaque = device_priv; device_ctx->free = device_free; device_hwctx->device = device; device_hwctx->get_proc_address = get_proc_address; device_priv = NULL; ret = av_hwdevice_ctx_init(device_ref); if (ret < 0) goto fail; ctx->hw_frames_ctx = av_hwframe_ctx_alloc(device_ref); if (!ctx->hw_frames_ctx) goto fail; //av_buffer_unref(&device_ref); frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; frames_ctx->format = AV_PIX_FMT_VDPAU; frames_ctx->sw_format = s->sw_pix_fmt; frames_ctx->width = 1920; frames_ctx->height = 1080; ret = av_hwframe_ctx_init(ctx->hw_frames_ctx); if (ret < 0) goto fail; if (av_vdpau_bind_context(s, device, get_proc_address, 0)) goto fail; s->opaque = ctx; return 0; fail: if (device_priv) { if (device_priv->device_destroy) device_priv->device_destroy(device); if (device_priv->dpy) XCloseDisplay(device_priv->dpy); } av_freep(&device_priv); av_buffer_unref(&device_ref); vdpau_uninit(s); return AVERROR(EINVAL); }
static int qsv_init_child_ctx(AVHWFramesContext *ctx) { AVQSVFramesContext *hwctx = ctx->hwctx; QSVFramesContext *s = ctx->internal->priv; QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv; AVBufferRef *child_device_ref = NULL; AVBufferRef *child_frames_ref = NULL; AVHWDeviceContext *child_device_ctx; AVHWFramesContext *child_frames_ctx; int i, ret = 0; if (!device_priv->handle) { av_log(ctx, AV_LOG_ERROR, "Cannot create a non-opaque internal surface pool without " "a hardware handle\n"); return AVERROR(EINVAL); } child_device_ref = av_hwdevice_ctx_alloc(device_priv->child_device_type); if (!child_device_ref) return AVERROR(ENOMEM); child_device_ctx = (AVHWDeviceContext*)child_device_ref->data; #if CONFIG_VAAPI if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) { AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx; child_device_hwctx->display = (VADisplay)device_priv->handle; } #endif #if CONFIG_DXVA2 if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx; child_device_hwctx->devmgr = (IDirect3DDeviceManager9*)device_priv->handle; } #endif ret = av_hwdevice_ctx_init(child_device_ref); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Error initializing a child device context\n"); goto fail; } child_frames_ref = av_hwframe_ctx_alloc(child_device_ref); if (!child_frames_ref) { ret = AVERROR(ENOMEM); goto fail; } child_frames_ctx = (AVHWFramesContext*)child_frames_ref->data; child_frames_ctx->format = device_priv->child_pix_fmt; child_frames_ctx->sw_format = ctx->sw_format; child_frames_ctx->initial_pool_size = ctx->initial_pool_size; child_frames_ctx->width = FFALIGN(ctx->width, 16); child_frames_ctx->height = FFALIGN(ctx->height, 16); #if CONFIG_DXVA2 if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx; if (hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) child_frames_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget; else child_frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; } #endif ret = av_hwframe_ctx_init(child_frames_ref); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Error initializing a child frames context\n"); goto fail; } #if CONFIG_VAAPI if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) { AVVAAPIFramesContext *child_frames_hwctx = child_frames_ctx->hwctx; for (i = 0; i < ctx->initial_pool_size; i++) s->surfaces_internal[i].Data.MemId = child_frames_hwctx->surface_ids + i; hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; } #endif #if CONFIG_DXVA2 if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx; for (i = 0; i < ctx->initial_pool_size; i++) s->surfaces_internal[i].Data.MemId = (mfxMemId)child_frames_hwctx->surfaces[i]; if (child_frames_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget) hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET; else hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; } #endif s->child_frames_ref = child_frames_ref; child_frames_ref = NULL; fail: av_buffer_unref(&child_device_ref); av_buffer_unref(&child_frames_ref); return ret; }
STDMETHODIMP CDecD3D11::PostConnect(IPin *pPin) { DbgLog((LOG_TRACE, 10, L"CDecD3D11::PostConnect()")); HRESULT hr = S_OK; ID3D11DecoderConfiguration *pD3D11DecoderConfiguration = nullptr; hr = pPin->QueryInterface(&pD3D11DecoderConfiguration); if (FAILED(hr)) { DbgLog((LOG_ERROR, 10, L"-> ID3D11DecoderConfiguration not available, using fallback mode")); } // Release old D3D resources, we're about to re-init m_pCallback->ReleaseAllDXVAResources(); // free the decoder to force a re-init down the line SafeRelease(&m_pDecoder); // and the old device av_buffer_unref(&m_pDevCtx); // device id UINT nDevice = m_pSettings->GetHWAccelDeviceIndex(HWAccel_D3D11, nullptr); // in automatic mode use the device the renderer gives us if (nDevice == LAVHWACCEL_DEVICE_DEFAULT && pD3D11DecoderConfiguration) { nDevice = pD3D11DecoderConfiguration->GetD3D11AdapterIndex(); } else { // if a device is specified manually, fallback to copy-back and use the selected device SafeRelease(&pD3D11DecoderConfiguration); // use the configured device if (nDevice == LAVHWACCEL_DEVICE_DEFAULT) nDevice = 0; } // create the device ID3D11Device *pD3D11Device = nullptr; hr = CreateD3D11Device(nDevice, &pD3D11Device, &m_AdapterDesc); if (FAILED(hr)) { goto fail; } // allocate and fill device context m_pDevCtx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA); AVD3D11VADeviceContext *pDeviceContext = (AVD3D11VADeviceContext *)((AVHWDeviceContext *)m_pDevCtx->data)->hwctx; pDeviceContext->device = pD3D11Device; // finalize the context int ret = av_hwdevice_ctx_init(m_pDevCtx); if (ret < 0) { av_buffer_unref(&m_pDevCtx); goto fail; } // check if the connection supports native mode if (pD3D11DecoderConfiguration) { CMediaType mt = m_pCallback->GetOutputMediaType(); if ((m_SurfaceFormat == DXGI_FORMAT_NV12 && mt.subtype != MEDIASUBTYPE_NV12) || (m_SurfaceFormat == DXGI_FORMAT_P010 && mt.subtype != MEDIASUBTYPE_P010) || (m_SurfaceFormat == DXGI_FORMAT_P016 && mt.subtype != MEDIASUBTYPE_P016)) { DbgLog((LOG_ERROR, 10, L"-> Connection is not the appropriate pixel format for D3D11 Native")); SafeRelease(&pD3D11DecoderConfiguration); } } // verify hardware support { GUID guidConversion = GUID_NULL; hr = FindVideoServiceConversion(m_pAVCtx->codec_id, m_pAVCtx->profile, m_SurfaceFormat, &guidConversion); if (FAILED(hr)) { goto fail; } // get decoder configuration D3D11_VIDEO_DECODER_DESC desc = { 0 }; desc.Guid = guidConversion; desc.OutputFormat = m_SurfaceFormat; desc.SampleWidth = m_pAVCtx->coded_width; desc.SampleHeight = m_pAVCtx->coded_height; D3D11_VIDEO_DECODER_CONFIG decoder_config = { 0 }; hr = FindDecoderConfiguration(&desc, &decoder_config); if (FAILED(hr)) { goto fail; } // test creating a texture D3D11_TEXTURE2D_DESC texDesc = { 0 }; texDesc.Width = m_pAVCtx->coded_width; texDesc.Height = m_pAVCtx->coded_height; texDesc.MipLevels = 1; texDesc.ArraySize = 10; texDesc.Format = m_SurfaceFormat; texDesc.SampleDesc.Count = 1; texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE; texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; ID3D11Texture2D *pTexture2D = nullptr; hr = pD3D11Device->CreateTexture2D(&texDesc, nullptr, &pTexture2D); if (FAILED(hr)) { goto fail; } SafeRelease(&pTexture2D); } // Notice the connected pin that we're sending D3D11 textures if (pD3D11DecoderConfiguration) { hr = pD3D11DecoderConfiguration->ActivateD3D11Decoding(pDeviceContext->device, pDeviceContext->device_context, pDeviceContext->lock_ctx, 0); SafeRelease(&pD3D11DecoderConfiguration); m_bReadBackFallback = FAILED(hr); } else { m_bReadBackFallback = true; } return S_OK; fail: SafeRelease(&pD3D11DecoderConfiguration); return E_FAIL; }