static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 format, void * pixels, int pitch) { D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; D3DSURFACE_DESC desc; LPDIRECT3DSURFACE9 backBuffer; LPDIRECT3DSURFACE9 surface; RECT d3drect; D3DLOCKED_RECT locked; HRESULT result; result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); if (FAILED(result)) { return D3D_SetError("GetBackBuffer()", result); } result = IDirect3DSurface9_GetDesc(backBuffer, &desc); if (FAILED(result)) { IDirect3DSurface9_Release(backBuffer); return D3D_SetError("GetDesc()", result); } result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL); if (FAILED(result)) { IDirect3DSurface9_Release(backBuffer); return D3D_SetError("CreateOffscreenPlainSurface()", result); } result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface); if (FAILED(result)) { IDirect3DSurface9_Release(surface); IDirect3DSurface9_Release(backBuffer); return D3D_SetError("GetRenderTargetData()", result); } d3drect.left = rect->x; d3drect.right = rect->x + rect->w; d3drect.top = rect->y; d3drect.bottom = rect->y + rect->h; result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY); if (FAILED(result)) { IDirect3DSurface9_Release(surface); IDirect3DSurface9_Release(backBuffer); return D3D_SetError("LockRect()", result); } SDL_ConvertPixels(rect->w, rect->h, D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch, format, pixels, pitch); IDirect3DSurface9_UnlockRect(surface); IDirect3DSurface9_Release(surface); IDirect3DSurface9_Release(backBuffer); return 0; }
static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src) { IDirect3DSurface9 *surface; D3DSURFACE_DESC surfaceDesc; D3DLOCKED_RECT LockedRect; HRESULT hr; int download = !!src->hw_frames_ctx; int bytes_per_component; switch (ctx->sw_format) { case AV_PIX_FMT_NV12: bytes_per_component = 1; break; case AV_PIX_FMT_P010: bytes_per_component = 2; break; default: av_assert0(0); } surface = (IDirect3DSurface9*)(download ? src->data[3] : dst->data[3]); hr = IDirect3DSurface9_GetDesc(surface, &surfaceDesc); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Error getting a surface description\n"); return AVERROR_UNKNOWN; } hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, download ? D3DLOCK_READONLY : D3DLOCK_DISCARD); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); return AVERROR_UNKNOWN; } if (download) { av_image_copy_plane(dst->data[0], dst->linesize[0], (uint8_t*)LockedRect.pBits, LockedRect.Pitch, src->width * bytes_per_component, src->height); av_image_copy_plane(dst->data[1], dst->linesize[1], (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height, LockedRect.Pitch, src->width * bytes_per_component, src->height / 2); } else { av_image_copy_plane((uint8_t*)LockedRect.pBits, LockedRect.Pitch, dst->data[0], dst->linesize[0], src->width * bytes_per_component, src->height); av_image_copy_plane((uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height, LockedRect.Pitch, dst->data[1], dst->linesize[1], src->width * bytes_per_component, src->height / 2); } IDirect3DSurface9_UnlockRect(surface); return 0; }
static int dxva2_map_frame(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags) { IDirect3DSurface9 *surface = (IDirect3DSurface9*)src->data[3]; DXVA2Mapping *map; D3DSURFACE_DESC surfaceDesc; D3DLOCKED_RECT LockedRect; HRESULT hr; int i, err, nb_planes; int lock_flags = 0; nb_planes = av_pix_fmt_count_planes(dst->format); hr = IDirect3DSurface9_GetDesc(surface, &surfaceDesc); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Error getting a surface description\n"); return AVERROR_UNKNOWN; } if (!(flags & AV_HWFRAME_MAP_WRITE)) lock_flags |= D3DLOCK_READONLY; if (flags & AV_HWFRAME_MAP_OVERWRITE) lock_flags |= D3DLOCK_DISCARD; hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, lock_flags); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); return AVERROR_UNKNOWN; } map = av_mallocz(sizeof(*map)); if (!map) goto fail; err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, dxva2_unmap_frame, map); if (err < 0) { av_freep(&map); goto fail; } for (i = 0; i < nb_planes; i++) dst->linesize[i] = LockedRect.Pitch; av_image_fill_pointers(dst->data, dst->format, surfaceDesc.Height, (uint8_t*)LockedRect.pBits, dst->linesize); if (dst->format == AV_PIX_FMT_PAL8) dst->data[1] = (uint8_t*)map->palette_dummy; return 0; fail: IDirect3DSurface9_UnlockRect(surface); return err; }
static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame) { LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)frame->data[3]; HwAccelContext *hac = s->opaque; DXVA2Context *ctx = hac->hwaccel_ctx; D3DSURFACE_DESC surfaceDesc; D3DLOCKED_RECT LockedRect; HRESULT hr; int ret; int i; IDirect3DSurface9_GetDesc(surface, &surfaceDesc); ctx->tmp_frame->width = frame->width; ctx->tmp_frame->height = frame->height; ctx->tmp_frame->format = AV_PIX_FMT_NV12; ret = av_frame_get_buffer(ctx->tmp_frame, 32); if (ret < 0) return ret; hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, D3DLOCK_READONLY); if (FAILED(hr)) { av_log(NULL, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); return AVERROR_UNKNOWN; } av_image_copy_plane(ctx->tmp_frame->data[0], ctx->tmp_frame->linesize[0], (uint8_t*)LockedRect.pBits, LockedRect.Pitch, frame->width, frame->height); av_image_copy_plane(ctx->tmp_frame->data[1], ctx->tmp_frame->linesize[1], (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height, LockedRect.Pitch, frame->width, frame->height / 2); IDirect3DSurface9_UnlockRect(surface); for (i = 0; i < ctx->num_surfaces; i++) { if (ctx->surfaces[i] == surface) { break; } } av_log(NULL, AV_LOG_DEBUG, "dxva2_retrieve_data:%d\n",i); ret = av_frame_copy_props(ctx->tmp_frame, frame); if (ret < 0) goto fail; av_frame_unref(frame); av_frame_move_ref(frame, ctx->tmp_frame); return 0; fail: av_frame_unref(ctx->tmp_frame); return ret; }
static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src) { IDirect3DSurface9 *surface; D3DSURFACE_DESC surfaceDesc; D3DLOCKED_RECT LockedRect; HRESULT hr; uint8_t *surf_data[4] = { NULL }; int surf_linesize[4] = { 0 }; int i; int download = !!src->hw_frames_ctx; surface = (IDirect3DSurface9*)(download ? src->data[3] : dst->data[3]); hr = IDirect3DSurface9_GetDesc(surface, &surfaceDesc); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Error getting a surface description\n"); return AVERROR_UNKNOWN; } hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, download ? D3DLOCK_READONLY : D3DLOCK_DISCARD); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); return AVERROR_UNKNOWN; } for (i = 0; download ? dst->data[i] : src->data[i]; i++) surf_linesize[i] = LockedRect.Pitch; av_image_fill_pointers(surf_data, ctx->sw_format, surfaceDesc.Height, (uint8_t*)LockedRect.pBits, surf_linesize); if (download) { ptrdiff_t src_linesize1[4], dst_linesize1[4]; for (i = 0; i < 4; i++) { dst_linesize1[i] = dst->linesize[i]; src_linesize1[i] = surf_linesize[i]; } av_image_copy_uc_from(dst->data, dst_linesize1, surf_data, src_linesize1, ctx->sw_format, src->width, src->height); } else { av_image_copy(surf_data, surf_linesize, src->data, src->linesize, ctx->sw_format, src->width, src->height); } IDirect3DSurface9_UnlockRect(surface); return 0; }
static struct mp_image *dxva2_retrieve_image(struct lavc_ctx *s, struct mp_image *img) { HRESULT hr; struct priv *p = s->hwdec_priv; IDirect3DSurface9 *surface = img->imgfmt == IMGFMT_DXVA2 ? (IDirect3DSurface9 *)img->planes[3] : NULL; if (!surface) { MP_ERR(p, "Failed to get Direct3D surface from mp_image\n"); return img; } D3DSURFACE_DESC surface_desc; IDirect3DSurface9_GetDesc(surface, &surface_desc); if (surface_desc.Width < img->w || surface_desc.Height < img->h) { MP_ERR(p, "Direct3D11 texture smaller than mp_image dimensions\n"); return img; } struct mp_image *sw_img = mp_image_pool_get(p->sw_pool, p->mpfmt_decoded, surface_desc.Width, surface_desc.Height); if (!sw_img) { MP_ERR(p, "Failed to get %s surface from CPU pool\n", mp_imgfmt_to_name(p->mpfmt_decoded)); return img; } D3DLOCKED_RECT lock; hr = IDirect3DSurface9_LockRect(surface, &lock, NULL, D3DLOCK_READONLY); if (FAILED(hr)) { MP_ERR(p, "Unable to lock DXVA2 surface: %s\n", mp_HRESULT_to_str(hr)); talloc_free(sw_img); return img; } copy_nv12(sw_img, lock.pBits, lock.Pitch, surface_desc.Height); IDirect3DSurface9_UnlockRect(surface); mp_image_set_size(sw_img, img->w, img->h); mp_image_copy_attributes(sw_img, img); talloc_free(img); return sw_img; }
HRESULT STDMETHODCALLTYPE IDirect3DDevice9_EndScene_Hook(IDirect3DDevice9* This) { static unsigned count = 0; auto ticks = []() { LARGE_INTEGER value; QueryPerformanceCounter(&value); return KSCONVERT_PERFORMANCE_TIME(frequency, value); }(); static auto start = [This, &ticks]() { IDirect3DSurface9* renderTarget; IDirect3DDevice9_GetRenderTarget(This, 0, &renderTarget); IDirect3DSurface9_GetDesc(renderTarget, &desc); IDirect3DSurface9_Release(renderTarget); // quick hack, first 'ticks - start' is 1. return ticks++; }(); fps = static_cast<unsigned>(static_cast<ULONGLONG>(++count) * NANOSECONDS / (ticks - start)); FramePtr frame = Frame; if (frame) { IDirect3DSurface9* offsecreen; check(TEXT("CreateOffscreenPlainSurface"), IDirect3DDevice9_CreateOffscreenPlainSurface(This, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &offsecreen, nullptr)); { IDirect3DSurface9* target; check(TEXT("GetRenderTarget"), IDirect3DDevice9_GetRenderTarget(This, 0, &target)); #if 0 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) { IDirect3DSurface9* resolved; check(TEXT("CreateRenderTarget"), IDirect3DDevice9_CreateRenderTarget(This, desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, false, &resolved, nullptr)); check(TEXT("StretchRect"), IDirect3DDevice9_StretchRect(This, target, nullptr, resolved, nullptr, D3DTEXF_NONE)); IDirect3DSurface9_Release(target); target = resolved; } #endif check(TEXT("GetRenderTargetData"), IDirect3DDevice9_GetRenderTargetData(This, target, offsecreen)); IDirect3DSurface9_Release(target); } frame(ticks, offsecreen); IDirect3DSurface9_Release(offsecreen); } return IDirect3DDevice9_EndScene_Orig(This); }
static struct mp_image *dxva2_retrieve_image(struct lavc_ctx *s, struct mp_image *img) { DXVA2Context *ctx = s->hwdec_priv; LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)img->planes[3]; D3DSURFACE_DESC surfaceDesc; D3DLOCKED_RECT LockedRect; HRESULT hr; IDirect3DSurface9_GetDesc(surface, &surfaceDesc); if (surfaceDesc.Width < img->w || surfaceDesc.Height < img->h) return img; struct mp_image *sw_img = mp_image_pool_get(ctx->sw_pool, IMGFMT_NV12, surfaceDesc.Width, surfaceDesc.Height); if (!sw_img) return img; hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, D3DLOCK_READONLY); if (FAILED(hr)) { MP_ERR(ctx, "Unable to lock DXVA2 surface\n"); talloc_free(sw_img); return img; } copy_nv12(sw_img, LockedRect.pBits, LockedRect.Pitch, surfaceDesc.Height); mp_image_set_size(sw_img, img->w, img->h); mp_image_copy_attributes(sw_img, img); IDirect3DSurface9_UnlockRect(surface); talloc_free(img); return sw_img; }
ILAPI ILboolean ILAPIENTRY ilutD3D9LoadSurface(IDirect3DDevice9 *Device, IDirect3DSurface9 *Surface) { HRESULT hr; D3DSURFACE_DESC d3dsd; LPDIRECT3DSURFACE9 SurfaceCopy; D3DLOCKED_RECT d3dLR; ILboolean bHasAlpha; ILubyte *Image, *ImageAux, *Data; ILuint y, x; ILushort dwColor; IDirect3DSurface9_GetDesc(Surface, &d3dsd); bHasAlpha = (d3dsd.Format == D3DFMT_A8R8G8B8 || d3dsd.Format == D3DFMT_A1R5G5B5); if (bHasAlpha) { if (!ilTexImage(d3dsd.Width, d3dsd.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } } else { if (!ilTexImage(d3dsd.Width, d3dsd.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } } hr = IDirect3DDevice9_CreateOffscreenPlainSurface(Device, d3dsd.Width, d3dsd.Height, d3dsd.Format, D3DPOOL_SCRATCH, &SurfaceCopy, NULL); if (FAILED(hr)) { ilSetError(ILUT_ILLEGAL_OPERATION); return IL_FALSE; } hr = IDirect3DDevice9_StretchRect(Device, Surface, NULL, SurfaceCopy, NULL, D3DTEXF_NONE); if (FAILED(hr)) { ilSetError(ILUT_ILLEGAL_OPERATION); return IL_FALSE; } hr = IDirect3DSurface9_LockRect(SurfaceCopy, &d3dLR, NULL, D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY); if (FAILED(hr)) { IDirect3DSurface9_Release(SurfaceCopy); ilSetError(ILUT_ILLEGAL_OPERATION); return IL_FALSE; } Image = (ILubyte*)d3dLR.pBits; Data = ilutCurImage->Data; for (y = 0; y < d3dsd.Height; y++) { if (d3dsd.Format == D3DFMT_X8R8G8B8) { ImageAux = Image; for (x = 0; x < d3dsd.Width; x++) { Data[0] = ImageAux[0]; Data[1] = ImageAux[1]; Data[2] = ImageAux[2]; Data += 3; ImageAux += 4; } } else if (d3dsd.Format == D3DFMT_A8R8G8B8) { memcpy(Data, Image, d3dsd.Width * 4); } else if (d3dsd.Format == D3DFMT_R5G6B5) { ImageAux = Image; for (x = 0; x < d3dsd.Width; x++) { dwColor = *((ILushort*)ImageAux); Data[0] = (ILubyte)((dwColor&0x001f)<<3); Data[1] = (ILubyte)(((dwColor&0x7e0)>>5)<<2); Data[2] = (ILubyte)(((dwColor&0xf800)>>11)<<3); Data += 3; ImageAux += 2; } } else if (d3dsd.Format == D3DFMT_X1R5G5B5) {
static int Open(vlc_object_t *obj) { filter_t *filter = (filter_t *)obj; filter_sys_t *sys = NULL; HINSTANCE hdecoder_dll = NULL; HINSTANCE d3d9_dll = NULL; HRESULT hr; picture_t *dst = NULL; GUID *processorGUIDs = NULL; GUID *processorGUID = NULL; IDirectXVideoProcessorService *processor = NULL; if (filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE && filter->fmt_in.video.i_chroma != VLC_CODEC_D3D9_OPAQUE_10B) return VLC_EGENERIC; if (!video_format_IsSimilar(&filter->fmt_in.video, &filter->fmt_out.video)) return VLC_EGENERIC; d3d9_dll = LoadLibrary(TEXT("D3D9.DLL")); if (!d3d9_dll) goto error; hdecoder_dll = LoadLibrary(TEXT("DXVA2.DLL")); if (!hdecoder_dll) goto error; dst = filter_NewPicture(filter); if (dst == NULL) goto error; if (!dst->p_sys) { msg_Dbg(filter, "D3D9 opaque without a texture"); goto error; } sys = calloc(1, sizeof (*sys)); if (unlikely(sys == NULL)) goto error; HRESULT (WINAPI *CreateVideoService)(IDirect3DDevice9 *, REFIID riid, void **ppService); CreateVideoService = (void *)GetProcAddress(hdecoder_dll, "DXVA2CreateVideoService"); if (CreateVideoService == NULL) goto error; hr = IDirect3DSurface9_GetDevice( dst->p_sys->surface, &sys->d3ddev ); if (FAILED(hr)) goto error; D3DSURFACE_DESC dstDesc; hr = IDirect3DSurface9_GetDesc( dst->p_sys->surface, &dstDesc ); if (unlikely(FAILED(hr))) goto error; hr = CreateVideoService( sys->d3ddev, &IID_IDirectXVideoProcessorService, (void**)&processor); if (FAILED(hr)) goto error; DXVA2_VideoDesc dsc; ZeroMemory(&dsc, sizeof(dsc)); dsc.SampleWidth = dstDesc.Width; dsc.SampleHeight = dstDesc.Height; dsc.Format = dstDesc.Format; if (filter->fmt_in.video.i_frame_rate && filter->fmt_in.video.i_frame_rate_base) { dsc.InputSampleFreq.Numerator = filter->fmt_in.video.i_frame_rate; dsc.InputSampleFreq.Denominator = filter->fmt_in.video.i_frame_rate_base; } else { dsc.InputSampleFreq.Numerator = 0; dsc.InputSampleFreq.Denominator = 0; } dsc.OutputFrameFreq = dsc.InputSampleFreq; DXVA2_ExtendedFormat *pFormat = &dsc.SampleFormat; pFormat->SampleFormat = dst->b_top_field_first ? DXVA2_SampleFieldInterleavedEvenFirst : DXVA2_SampleFieldInterleavedOddFirst; UINT count = 0; hr = IDirectXVideoProcessorService_GetVideoProcessorDeviceGuids( processor, &dsc, &count, &processorGUIDs); if (FAILED(hr)) goto error; char *psz_mode = var_InheritString( filter, "deinterlace-mode" ); const struct filter_mode_t *p_mode = GetFilterMode(psz_mode); if (p_mode == NULL) { msg_Dbg(filter, "unknown mode %s, trying blend", psz_mode); p_mode = GetFilterMode("blend"); } if (strcmp(p_mode->psz_mode, psz_mode)) msg_Dbg(filter, "using %s deinterlacing mode", p_mode->psz_mode); DXVA2_VideoProcessorCaps caps, best_caps; unsigned best_score = 0; for (UINT i=0; i<count; ++i) { hr = IDirectXVideoProcessorService_GetVideoProcessorCaps( processor, processorGUIDs+i, &dsc, dsc.Format, &caps); if ( FAILED(hr) || !caps.DeinterlaceTechnology ) continue; unsigned score = (caps.DeinterlaceTechnology & p_mode->i_mode) ? 10 : 1; if (best_score < score) { best_score = score; best_caps = caps; processorGUID = processorGUIDs + i; } } if (processorGUID == NULL) { msg_Dbg(filter, "Could not find a filter to output the required format"); goto error; } hr = IDirectXVideoProcessorService_CreateVideoProcessor( processor, processorGUID, &dsc, dsc.Format, 1, &sys->processor ); if (FAILED(hr)) goto error; hr = IDirectXVideoProcessorService_CreateSurface( processor, dstDesc.Width, dstDesc.Height, 0, dstDesc.Format, D3DPOOL_DEFAULT, 0, DXVA2_VideoProcessorRenderTarget, &sys->hw_surface, NULL); if (FAILED(hr)) goto error; sys->hdecoder_dll = hdecoder_dll; sys->d3d9_dll = d3d9_dll; sys->decoder_caps = best_caps; InitDeinterlacingContext( &sys->context ); sys->context.settings = p_mode->settings; sys->context.settings.b_use_frame_history = best_caps.NumBackwardRefSamples != 0 || best_caps.NumForwardRefSamples != 0; if (sys->context.settings.b_use_frame_history != p_mode->settings.b_use_frame_history) msg_Dbg( filter, "deinterlacing not using frame history as requested"); if (sys->context.settings.b_double_rate) sys->context.pf_render_ordered = RenderPic; else sys->context.pf_render_single_pic = RenderSinglePic; video_format_t out_fmt; GetDeinterlacingOutput( &sys->context, &out_fmt, &filter->fmt_in.video ); if( !filter->b_allow_fmt_out_change && out_fmt.i_height != filter->fmt_in.video.i_height ) { goto error; } CoTaskMemFree(processorGUIDs); IDirectXVideoProcessorService_Release(processor); picture_Release(dst); sys->buffer_new = filter->owner.video.buffer_new; filter->owner.video.buffer_new = NewOutputPicture; filter->fmt_out.video = out_fmt; filter->pf_video_filter = Deinterlace; filter->pf_flush = Flush; filter->p_sys = sys; return VLC_SUCCESS; error: CoTaskMemFree(processorGUIDs); if (sys && sys->processor) IDirectXVideoProcessor_Release( sys->processor ); if (processor) IDirectXVideoProcessorService_Release(processor); if (sys && sys->d3ddev) IDirect3DDevice9_Release( sys->d3ddev ); if (hdecoder_dll) FreeLibrary(hdecoder_dll); if (d3d9_dll) FreeLibrary(d3d9_dll); if (dst) picture_Release(dst); free(sys); return VLC_EGENERIC; }
static int RenderPic( filter_t *filter, picture_t *p_outpic, picture_t *src, int order, int i_field ) { filter_sys_t *sys = filter->p_sys; const int i_samples = sys->decoder_caps.NumBackwardRefSamples + 1 + sys->decoder_caps.NumForwardRefSamples; HRESULT hr; DXVA2_VideoProcessBltParams params; DXVA2_VideoSample samples[i_samples]; picture_t *pictures[i_samples]; D3DSURFACE_DESC srcDesc, dstDesc; RECT area; picture_t *p_prev = sys->context.pp_history[0]; picture_t *p_cur = sys->context.pp_history[1]; picture_t *p_next = sys->context.pp_history[2]; picture_sys_t *p_sys_src = ActivePictureSys(src); hr = IDirect3DSurface9_GetDesc( p_sys_src->surface, &srcDesc ); if (unlikely(FAILED(hr))) return VLC_EGENERIC; hr = IDirect3DSurface9_GetDesc( sys->hw_surface, &dstDesc ); if (unlikely(FAILED(hr))) return VLC_EGENERIC; area.top = area.left = 0; area.bottom = __MIN(srcDesc.Height, dstDesc.Height); area.right = __MIN(srcDesc.Width, dstDesc.Width); int idx = i_samples - 1; if (p_next) { pictures[idx--] = p_next; if (p_cur) pictures[idx--] = p_cur; if (p_prev) pictures[idx--] = p_prev; } else pictures[idx--] = src; while (idx >= 0) pictures[idx--] = NULL; for (idx = 0; idx <= i_samples-1; idx++) { if (pictures[idx]) FillSample( &samples[idx], &sys->context, pictures[idx], &filter->fmt_out.video, &area, i_field); else { FillSample( &samples[idx], &sys->context, src, &filter->fmt_out.video, &area, i_field); samples[idx].SampleFormat.SampleFormat = DXVA2_SampleUnknown; } } FillBlitParams( ¶ms, &area, samples, order ); hr = IDirectXVideoProcessor_VideoProcessBlt( sys->processor, sys->hw_surface, ¶ms, samples, i_samples, NULL ); if (FAILED(hr)) return VLC_EGENERIC; hr = IDirect3DDevice9_StretchRect( sys->d3ddev, sys->hw_surface, NULL, p_outpic->p_sys->surface, NULL, D3DTEXF_NONE); if (FAILED(hr)) return VLC_EGENERIC; return VLC_SUCCESS; }
static int Open(vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, const es_format_t *fmt, picture_sys_t *p_sys) { int err = VLC_EGENERIC; directx_sys_t *dx_sys; if (pix_fmt != AV_PIX_FMT_DXVA2_VLD) return VLC_EGENERIC; ctx->hwaccel_context = NULL; vlc_va_sys_t *sys = calloc(1, sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; /* Load dll*/ sys->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL")); if (!sys->hd3d9_dll) { msg_Warn(va, "cannot load d3d9.dll"); goto error; } dx_sys = &sys->dx_sys; dx_sys->va_pool.pf_create_device = D3dCreateDevice; dx_sys->va_pool.pf_destroy_device = D3dDestroyDevice; dx_sys->va_pool.pf_create_device_manager = D3dCreateDeviceManager; dx_sys->va_pool.pf_destroy_device_manager = D3dDestroyDeviceManager; dx_sys->va_pool.pf_create_video_service = DxCreateVideoService; dx_sys->va_pool.pf_destroy_video_service = DxDestroyVideoService; dx_sys->va_pool.pf_create_decoder_surfaces = DxCreateVideoDecoder; dx_sys->va_pool.pf_destroy_surfaces = DxDestroyVideoDecoder; dx_sys->va_pool.pf_setup_avcodec_ctx = SetupAVCodecContext; dx_sys->va_pool.pf_new_surface_context = NewSurfacePicContext; dx_sys->pf_get_input_list = DxGetInputList; dx_sys->pf_setup_output = DxSetupOutput; dx_sys->psz_decoder_dll = TEXT("DXVA2.DLL"); va->sys = sys; dx_sys->d3ddev = NULL; if (p_sys!=NULL) { D3DSURFACE_DESC src; if (SUCCEEDED(IDirect3DSurface9_GetDesc(p_sys->surface, &src))) sys->render = src.Format; IDirect3DSurface9_GetDevice(p_sys->surface, &dx_sys->d3ddev ); } err = directx_va_Open(va, &sys->dx_sys, true); if (err!=VLC_SUCCESS) goto error; err = directx_va_Setup(va, &sys->dx_sys, ctx, fmt); if (err != VLC_SUCCESS) goto error; ctx->hwaccel_context = &sys->hw; /* TODO print the hardware name/vendor for debugging purposes */ va->description = DxDescribe(sys); va->get = Get; return VLC_SUCCESS; error: Close(va, NULL); return VLC_EGENERIC; }