/** \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; }
/** @brief Destroy D3D Offscreen and Backbuffer surfaces. */ static void destroy_d3d_surfaces(void) { mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>destroy_d3d_surfaces called.\n"); /* Let's destroy the old (if any) D3D Surfaces */ if (priv->locked_rect.pBits) IDirect3DSurface9_UnlockRect(priv->d3d_surface); priv->locked_rect.pBits = NULL; if (priv->d3d_surface) IDirect3DSurface9_Release(priv->d3d_surface); priv->d3d_surface = NULL; /* kill the OSD texture and its shadow copy */ if (priv->d3d_texture_osd) IDirect3DTexture9_Release(priv->d3d_texture_osd); priv->d3d_texture_osd = NULL; if (priv->d3d_texture_system) IDirect3DTexture9_Release(priv->d3d_texture_system); priv->d3d_texture_system = NULL; if (priv->d3d_backbuf) IDirect3DSurface9_Release(priv->d3d_backbuf); priv->d3d_backbuf = NULL; }
/** * 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 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; }
/** * It unlocks the surface associated to the picture. */ static void Direct3DUnlockSurface(picture_t *picture) { /* Unlock the Surface */ HRESULT hr = IDirect3DSurface9_UnlockRect(picture->p_sys->surface); if (FAILED(hr)) { //msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); } }
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; }
void d3d_unlock_rectangle(LPDIRECT3DTEXTURE tex) { #ifdef _XBOX D3DTexture_UnlockRect(tex, 0); #else #if defined(HAVE_D3D9) && !defined(__cplusplus) IDirect3DSurface9_UnlockRect(tex); #else tex->UnlockRect(0); #endif #endif }
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; }
static HRESULT WINAPI IDirect3DCubeTexture9Impl_UnlockRect(IDirect3DCubeTexture9 *iface, D3DCUBEMAP_FACES face, UINT level) { IDirect3DCubeTexture9Impl *texture = impl_from_IDirect3DCubeTexture9(iface); struct wined3d_resource *sub_resource; UINT sub_resource_idx; HRESULT hr; TRACE("iface %p, face %#x, level %u.\n", iface, face, level); 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 hr = IDirect3DSurface9_UnlockRect((IDirect3DSurface9 *)wined3d_resource_get_parent(sub_resource)); wined3d_mutex_unlock(); return hr; }
static HRESULT WINAPI d3d9_texture_2d_UnlockRect(IDirect3DTexture9 *iface, UINT level) { struct d3d9_texture *texture = impl_from_IDirect3DTexture9(iface); struct wined3d_resource *sub_resource; struct d3d9_surface *surface_impl; HRESULT hr; TRACE("iface %p, level %u.\n", iface, level); wined3d_mutex_lock(); if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, level))) hr = D3DERR_INVALIDCALL; else { surface_impl = wined3d_resource_get_parent(sub_resource); hr = IDirect3DSurface9_UnlockRect(&surface_impl->IDirect3DSurface9_iface); } wined3d_mutex_unlock(); return hr; }
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; }
/** @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 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; }
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 void dxva2_unmap_frame(AVHWFramesContext *ctx, HWMapDescriptor *hwmap) { IDirect3DSurface9 *surface = (IDirect3DSurface9*)hwmap->source->data[3]; IDirect3DSurface9_UnlockRect(surface); av_freep(&hwmap->priv); }