/** \fn ADMImage_To_argbSurface */ static bool ADMImage_To_argbSurface(ADMImage *pic, IDirect3DSurface9 *surface,ADMColorScalerFull *scaler) { D3DLOCKED_RECT lock; if (ADM_FAILED(IDirect3DSurface9_LockRect(surface,&lock, NULL, 0))) { ADM_warning("D3D Cannot lock surface\n"); return false; } // RGB uint8_t *src[3]; uint8_t *dst[3]; pic->GetReadPlanes(src); dst[0]=(uint8_t *)lock.pBits; dst[1]=dst[2]=NULL; int sourcePitch[3],dstPitch[3]; pic->GetPitches(sourcePitch); dstPitch[0]=lock.Pitch; dstPitch[1]=dstPitch[2]=0; scaler-> convertPlanes(sourcePitch,dstPitch, src, dst); if (ADM_FAILED(IDirect3DSurface9_UnlockRect(surface))) { ADM_warning("D3D Cannot unlock surface\n"); return false; } return true; }
/** \fn ADMImage_To_yv12Surface */ static bool ADMImage_To_yv12Surface(ADMImage *pic, IDirect3DSurface9 *surface) { D3DLOCKED_RECT lock;; if (ADM_FAILED(IDirect3DSurface9_LockRect(surface,&lock, NULL, 0))) { ADM_warning("D3D Cannot lock surface\n"); return false; } // copy uint8_t *dst=(uint8_t *)lock.pBits; int dStride=lock.Pitch; int width=pic->GetWidth(PLANAR_Y); int height=pic->GetHeight(PLANAR_Y); d3dBlit(pic, PLANAR_Y,dst,dStride,width,height); dst+=height*dStride; d3dBlit(pic, PLANAR_U,dst,dStride>>1,width>>1,height>>1); dst+=(height/2)*(dStride/2); d3dBlit(pic, PLANAR_V,dst,dStride>>1,width>>1,height>>1); if (ADM_FAILED(IDirect3DSurface9_UnlockRect(surface))) { ADM_warning("D3D Cannot unlock surface\n"); return false; } return true; }
/** * lock frame data form surface. * nv12 to yuv with opencl and with C reference * scale with opencl */ int hb_va_extract( hb_va_dxva2_t *dxva2, uint8_t *dst, AVFrame *frame, int job_w, int job_h, int *crop, hb_oclscale_t *os, int use_opencl, int use_decomb, int use_detelecine ) { LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)frame->data[3]; D3DLOCKED_RECT lock; if( FAILED( IDirect3DSurface9_LockRect( d3d, &lock, NULL, D3DLOCK_READONLY ))) { hb_log( "dxva2:Failed to lock surface" ); return HB_WORK_ERROR; } if( dxva2->render == MAKEFOURCC( 'N', 'V', '1', '2' )) { uint8_t *plane[2] = { lock.pBits, (uint8_t*)lock.pBits + lock.Pitch * dxva2->surface_height }; size_t pitch[2] = { lock.Pitch, lock.Pitch, }; hb_copy_from_nv12( dst, plane, pitch, dxva2->width, dxva2->height ); } IDirect3DSurface9_UnlockRect( d3d ); return HB_WORK_OK; }
static HRESULT WINAPI d3d9_texture_cube_LockRect(IDirect3DCubeTexture9 *iface, D3DCUBEMAP_FACES face, UINT level, D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags) { struct d3d9_texture *texture = impl_from_IDirect3DCubeTexture9(iface); struct wined3d_resource *sub_resource; struct d3d9_surface *surface_impl; UINT sub_resource_idx; HRESULT hr; TRACE("iface %p, face %#x, level %u, locked_rect %p, rect %p, flags %#x.\n", iface, face, level, locked_rect, rect, flags); wined3d_mutex_lock(); sub_resource_idx = wined3d_texture_get_level_count(texture->wined3d_texture) * face + level; if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx))) hr = D3DERR_INVALIDCALL; else { surface_impl = wined3d_resource_get_parent(sub_resource); hr = IDirect3DSurface9_LockRect(&surface_impl->IDirect3DSurface9_iface, locked_rect, rect, flags); } wined3d_mutex_unlock(); return hr; }
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; }
/** @brief libvo Callback: Draw slice * @return 0 on success */ static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y ) { char *my_src; /**< Pointer to the source image */ char *dst; /**< Pointer to the destination image */ int uv_stride; /**< Stride of the U/V planes */ /* If the D3D device is uncooperative (not initialized), return success. The device will be probed for reinitialization in the next flip_page() */ if (!priv->d3d_device) return 0; /* Lock the offscreen surface if it's not already locked. */ if (!priv->locked_rect.pBits) { if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, &priv->locked_rect, NULL, 0))) { mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface lock failure.\n"); return VO_FALSE; } } uv_stride = priv->locked_rect.Pitch / 2; /* Copy Y */ dst = priv->locked_rect.pBits; dst = dst + priv->locked_rect.Pitch * y + x; my_src = src[0]; memcpy_pic(dst, my_src, w, h, priv->locked_rect.Pitch, stride[0]); w /= 2; h /= 2; x /= 2; y /= 2; /* Copy U */ dst = priv->locked_rect.pBits; dst = dst + priv->locked_rect.Pitch * priv->src_height + uv_stride * y + x; if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2')) my_src = src[2]; else my_src = src[1]; memcpy_pic(dst, my_src, w, h, uv_stride, stride[1]); /* Copy V */ dst = priv->locked_rect.pBits; dst = dst + priv->locked_rect.Pitch * priv->src_height + uv_stride * (priv->src_height / 2) + uv_stride * y + x; if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2')) my_src=src[1]; else my_src=src[2]; memcpy_pic(dst, my_src, w, h, uv_stride, stride[2]); return 0; /* Success */ }
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; }
/** * It locks the surface associated to the picture and get the surface * descriptor which amongst other things has the pointer to the picture * data and its pitch. */ static int Direct3DLockSurface(picture_t *picture) { /* Lock the surface to get a valid pointer to the picture buffer */ D3DLOCKED_RECT d3drect; HRESULT hr = IDirect3DSurface9_LockRect(picture->p_sys->surface, &d3drect, NULL, 0); if (FAILED(hr)) { //msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return CommonUpdatePicture(picture, &picture->p_sys->fallback, NULL, 0); } CommonUpdatePicture(picture, NULL, d3drect.pBits, d3drect.Pitch); return VLC_SUCCESS; }
bool d3d_lock_rectangle(LPDIRECT3DTEXTURE tex, unsigned level, D3DLOCKED_RECT *lock_rect, RECT *rect, unsigned rectangle_height, unsigned flags) { #if defined(_XBOX) D3DTexture_LockRect(tex, level, lock_rect, rect, flags); #elif defined(HAVE_D3D9) && !defined(__cplusplus) if (IDirect3DSurface9_LockRect(tex, lock_rect, rect, flags) != D3D_OK) return false; #else if (FAILED(tex->LockRect(level, lock_rect, rect, flags))) return false; #endif return true; }
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; }
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) {
/** @brief Render a frame on the screen. * @param mpi mpi structure with the decoded frame inside * @return VO_TRUE on success, VO_ERROR on failure */ static uint32_t render_d3d_frame(mp_image_t *mpi) { /* Uncomment when direct rendering is implemented. * if (mpi->flags & MP_IMGFLAG_DIRECT) ... */ /* If the D3D device is uncooperative (not initialized), return success. The device will be probed for reinitialization in the next flip_page() */ if (!priv->d3d_device) return VO_TRUE; if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) goto skip_upload; if (mpi->flags & MP_IMGFLAG_PLANAR) { /* Copy a planar frame. */ draw_slice(mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0); goto skip_upload; } /* If we're here, then we should lock the rect and copy a packed frame */ if (!priv->locked_rect.pBits) { if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface, &priv->locked_rect, NULL, 0))) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Surface lock failed.\n"); return VO_ERROR; } } memcpy_pic(priv->locked_rect.pBits, mpi->planes[0], mpi->stride[0], mpi->height, priv->locked_rect.Pitch, mpi->stride[0]); skip_upload: /* This unlock is used for both slice_draw path and render_d3d_frame path. */ if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface))) { mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface unlock failed.\n"); return VO_ERROR; } priv->locked_rect.pBits = NULL; if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>BeginScene failed.\n"); return VO_ERROR; } if (priv->is_clear_needed) { IDirect3DDevice9_Clear(priv->d3d_device, 0, NULL, D3DCLEAR_TARGET, 0, 0, 0); priv->is_clear_needed = 0; } if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device, priv->d3d_surface, &priv->fs_panscan_rect, priv->d3d_backbuf, &priv->fs_movie_rect, D3DTEXF_LINEAR))) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Copying frame to the backbuffer failed.\n"); return VO_ERROR; } if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>EndScene failed.\n"); return VO_ERROR; } return VO_TRUE; }
static int Extract(vlc_va_t *va, picture_t *picture, void *opaque, uint8_t *data) { vlc_va_sys_t *sys = va->sys; LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)data; if (!sys->surface_cache.buffer) return VLC_EGENERIC; /* */ assert(sys->output == MAKEFOURCC('Y','V','1','2')); /* */ D3DLOCKED_RECT lock; if (FAILED(IDirect3DSurface9_LockRect(d3d, &lock, NULL, D3DLOCK_READONLY))) { msg_Err(va, "Failed to lock surface"); return VLC_EGENERIC; } if (sys->render == MAKEFOURCC('Y','V','1','2') || sys->render == MAKEFOURCC('I','M','C','3')) { bool imc3 = sys->render == MAKEFOURCC('I','M','C','3'); size_t chroma_pitch = imc3 ? lock.Pitch : (lock.Pitch / 2); size_t pitch[3] = { lock.Pitch, chroma_pitch, chroma_pitch, }; uint8_t *plane[3] = { (uint8_t*)lock.pBits, (uint8_t*)lock.pBits + pitch[0] * sys->surface_height, (uint8_t*)lock.pBits + pitch[0] * sys->surface_height + pitch[1] * sys->surface_height / 2, }; if (imc3) { uint8_t *V = plane[1]; plane[1] = plane[2]; plane[2] = V; } CopyFromYv12(picture, plane, pitch, sys->width, sys->height, &sys->surface_cache); } else { assert(sys->render == MAKEFOURCC('N','V','1','2')); uint8_t *plane[2] = { lock.pBits, (uint8_t*)lock.pBits + lock.Pitch * sys->surface_height }; size_t pitch[2] = { lock.Pitch, lock.Pitch, }; CopyFromNv12(picture, plane, pitch, sys->width, sys->height, &sys->surface_cache); } /* */ IDirect3DSurface9_UnlockRect(d3d); (void) opaque; return VLC_SUCCESS; }
static int Extract(vlc_va_t *external, picture_t *picture, AVFrame *ff) { vlc_va_dxva2_t *va = vlc_va_dxva2_Get(external); LPDIRECT3DSURFACE9 d3d = (LPDIRECT3DSURFACE9)(uintptr_t)ff->data[3]; if (!va->surface_cache.buffer) return VLC_EGENERIC; /* */ assert(va->output == MAKEFOURCC('Y','V','1','2')); /* */ D3DLOCKED_RECT lock; if (FAILED(IDirect3DSurface9_LockRect(d3d, &lock, NULL, D3DLOCK_READONLY))) { msg_Err(va->log, "Failed to lock surface"); return VLC_EGENERIC; } if (va->render == MAKEFOURCC('Y','V','1','2') || va->render == MAKEFOURCC('I','M','C','3')) { bool imc3 = va->render == MAKEFOURCC('I','M','C','3'); size_t chroma_pitch = imc3 ? lock.Pitch : (lock.Pitch / 2); size_t pitch[3] = { lock.Pitch, chroma_pitch, chroma_pitch, }; uint8_t *plane[3] = { (uint8_t*)lock.pBits, (uint8_t*)lock.pBits + pitch[0] * va->surface_height, (uint8_t*)lock.pBits + pitch[0] * va->surface_height + pitch[1] * va->surface_height / 2, }; if (imc3) { uint8_t *V = plane[1]; plane[1] = plane[2]; plane[2] = V; } CopyFromYv12(picture, plane, pitch, va->width, va->height, &va->surface_cache); } else { assert(va->render == MAKEFOURCC('N','V','1','2')); uint8_t *plane[2] = { lock.pBits, (uint8_t*)lock.pBits + lock.Pitch * va->surface_height }; size_t pitch[2] = { lock.Pitch, lock.Pitch, }; CopyFromNv12(picture, plane, pitch, va->width, va->height, &va->surface_cache); } /* */ IDirect3DSurface9_UnlockRect(d3d); return VLC_SUCCESS; }
static GstFlowReturn gst_dx9screencapsrc_create (GstPushSrc * push_src, GstBuffer ** buf) { GstDX9ScreenCapSrc *src = GST_DX9SCREENCAPSRC (push_src); GstBuffer *new_buf; gint new_buf_size, i; gint width, height, stride; GstClock *clock; GstClockTime buf_time, buf_dur; D3DLOCKED_RECT locked_rect; LPBYTE p_dst, p_src; HRESULT hres; GstMapInfo map; guint64 frame_number; if (G_UNLIKELY (!src->d3d9_device)) { GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), ("format wasn't negotiated before create function")); return GST_FLOW_NOT_NEGOTIATED; } clock = gst_element_get_clock (GST_ELEMENT (src)); if (clock != NULL) { GstClockTime time, base_time; /* Calculate sync time. */ time = gst_clock_get_time (clock); base_time = gst_element_get_base_time (GST_ELEMENT (src)); buf_time = time - base_time; if (src->rate_numerator) { frame_number = gst_util_uint64_scale (buf_time, src->rate_numerator, GST_SECOND * src->rate_denominator); } else { frame_number = -1; } } else { buf_time = GST_CLOCK_TIME_NONE; frame_number = -1; } if (frame_number != -1 && frame_number == src->frame_number) { GstClockID id; GstClockReturn ret; /* Need to wait for the next frame */ frame_number += 1; /* Figure out what the next frame time is */ buf_time = gst_util_uint64_scale (frame_number, src->rate_denominator * GST_SECOND, src->rate_numerator); id = gst_clock_new_single_shot_id (clock, buf_time + gst_element_get_base_time (GST_ELEMENT (src))); GST_OBJECT_LOCK (src); src->clock_id = id; GST_OBJECT_UNLOCK (src); GST_DEBUG_OBJECT (src, "Waiting for next frame time %" G_GUINT64_FORMAT, buf_time); ret = gst_clock_id_wait (id, NULL); GST_OBJECT_LOCK (src); gst_clock_id_unref (id); src->clock_id = NULL; if (ret == GST_CLOCK_UNSCHEDULED) { /* Got woken up by the unlock function */ GST_OBJECT_UNLOCK (src); return GST_FLOW_FLUSHING; } GST_OBJECT_UNLOCK (src); /* Duration is a complete 1/fps frame duration */ buf_dur = gst_util_uint64_scale_int (GST_SECOND, src->rate_denominator, src->rate_numerator); } else if (frame_number != -1) { GstClockTime next_buf_time; GST_DEBUG_OBJECT (src, "No need to wait for next frame time %" G_GUINT64_FORMAT " next frame = %" G_GINT64_FORMAT " prev = %" G_GINT64_FORMAT, buf_time, frame_number, src->frame_number); next_buf_time = gst_util_uint64_scale (frame_number + 1, src->rate_denominator * GST_SECOND, src->rate_numerator); /* Frame duration is from now until the next expected capture time */ buf_dur = next_buf_time - buf_time; } else { buf_dur = GST_CLOCK_TIME_NONE; } src->frame_number = frame_number; height = (src->src_rect.bottom - src->src_rect.top); width = (src->src_rect.right - src->src_rect.left); new_buf_size = width * 4 * height; GST_LOG_OBJECT (src, "creating buffer of %d bytes with %dx%d image", new_buf_size, width, height); /* Do screen capture and put it into buffer... * Aquire front buffer, and lock it */ hres = IDirect3DDevice9_GetFrontBufferData (src->d3d9_device, 0, src->surface); if (FAILED (hres)) { GST_DEBUG_OBJECT (src, "DirectX::GetBackBuffer failed."); return GST_FLOW_ERROR; } if (src->show_cursor) { CURSORINFO ci; ci.cbSize = sizeof (CURSORINFO); GetCursorInfo (&ci); if (ci.flags & CURSOR_SHOWING) { ICONINFO ii; HDC memDC; GetIconInfo (ci.hCursor, &ii); if (SUCCEEDED (IDirect3DSurface9_GetDC (src->surface, &memDC))) { HCURSOR cursor = CopyImage (ci.hCursor, IMAGE_CURSOR, 0, 0, LR_MONOCHROME | LR_DEFAULTSIZE); DrawIcon (memDC, ci.ptScreenPos.x - ii.xHotspot - src->monitor_info.rcMonitor.left, ci.ptScreenPos.y - ii.yHotspot - src->monitor_info.rcMonitor.top, cursor); DestroyCursor (cursor); IDirect3DSurface9_ReleaseDC (src->surface, memDC); } DeleteObject (ii.hbmColor); DeleteObject (ii.hbmMask); } } hres = IDirect3DSurface9_LockRect (src->surface, &locked_rect, &(src->src_rect), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY); if (FAILED (hres)) { GST_DEBUG_OBJECT (src, "DirectX::LockRect failed."); return GST_FLOW_ERROR; } new_buf = gst_buffer_new_and_alloc (new_buf_size); gst_buffer_map (new_buf, &map, GST_MAP_WRITE); p_dst = (LPBYTE) map.data; p_src = (LPBYTE) locked_rect.pBits; stride = width * 4; for (i = 0; i < height; ++i) { memcpy (p_dst, p_src, stride); p_dst += stride; p_src += locked_rect.Pitch; } gst_buffer_unmap (new_buf, &map); /* Unlock copy of front buffer */ IDirect3DSurface9_UnlockRect (src->surface); GST_BUFFER_TIMESTAMP (new_buf) = buf_time; GST_BUFFER_DURATION (new_buf) = buf_dur; if (clock != NULL) gst_object_unref (clock); *buf = new_buf; return GST_FLOW_OK; }
int video_canvas_refresh_dx9(video_canvas_t *canvas, unsigned int xs, unsigned int ys, unsigned int xi, unsigned int yi, unsigned int w, unsigned int h) { HRESULT stretchresult; LPDIRECT3DSURFACE9 d3dbackbuffer = NULL; D3DLOCKED_RECT lockedrect; if (canvas->videoconfig->doublesizex) { xi *= (canvas->videoconfig->doublesizex + 1); w *= (canvas->videoconfig->doublesizex + 1); } if (canvas->videoconfig->doublesizey) { yi *= (canvas->videoconfig->doublesizey + 1); h *= (canvas->videoconfig->doublesizey + 1); } if (S_OK != video_canvas_prepare_for_update(canvas)) { return -1; } if (S_OK != IDirect3DDevice9_Clear(canvas->d3ddev, 0, NULL, D3DCLEAR_TARGET, 0, 0, 0) || S_OK != IDirect3DDevice9_BeginScene(canvas->d3ddev) || S_OK != IDirect3DDevice9_GetBackBuffer(canvas->d3ddev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &d3dbackbuffer) || S_OK != IDirect3DSurface9_LockRect(canvas->d3dsurface, &lockedrect, NULL, 0)) { log_debug("video_dx9: Failed to prepare for rendering!"); return -1; } video_canvas_render(canvas, lockedrect.pBits, w, h, xs, ys, xi, yi, lockedrect.Pitch, 32); //video_save_screen ("c:\\temp\\screens\\", w, h, 32, lockedrect.pBits); if (S_OK != IDirect3DSurface9_UnlockRect(canvas->d3dsurface)) { log_debug("video_dx9: Failed to unlock surface!"); return -1; } do { stretchresult = IDirect3DDevice9_StretchRect(canvas->d3ddev, canvas->d3dsurface, NULL, d3dbackbuffer, canvas->dest_rect_ptr, d3dpreffilter); if (d3dpreffilter == D3DTEXF_NONE) { break; } if (stretchresult != S_OK) { /* Some adapters don't support filtering */ d3dpreffilter = D3DTEXF_NONE; log_debug("video_dx9: Disabled StretchRect filtering!"); } } while (stretchresult != S_OK); if (stretchresult != S_OK) { log_debug("video_dx9: StretchRect failed even without filtering!"); } if (S_OK != IDirect3DSurface9_Release(d3dbackbuffer) || S_OK != IDirect3DDevice9_EndScene(canvas->d3ddev)) { log_debug("video_dx9: EndScene failed!"); return -1; } if (S_OK != IDirect3DDevice9_Present(canvas->d3ddev, NULL, NULL, NULL, NULL)) { log_debug("video_dx9: Refresh failed to present the scene!"); return -1; } return 0; }