Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (10)
Showing with 855 additions and 137 deletions
......@@ -196,16 +196,24 @@ BUILT_SOURCES += access/screen/screenshooter-client-protocol.h
access_LTLIBRARIES += libwl_screenshooter_plugin.la
endif
libscreen_plugin_la_SOURCES = access/screen/screen.c access/screen/screen.h
libscreen_plugin_la_LDFLAGS = $(AM_LDFLAGS)
libscreen_win_plugin_la_SOURCES = access/screen/screen.c access/screen/screen.h \
access/screen/dxgi.cpp
libscreen_win_plugin_la_LIBADD = libd3d11_common.la $(LIBCOM) -luuid
if HAVE_WINSTORE
libscreen_win_plugin_la_LIBADD += -ld3d11
endif
if HAVE_WIN32_DESKTOP
libscreen_plugin_la_SOURCES += access/screen/win32.c
libscreen_plugin_la_LIBADD = -lgdi32
access_LTLIBRARIES += libscreen_plugin.la
libscreen_win_plugin_la_SOURCES += access/screen/win32.c
libscreen_win_plugin_la_LIBADD += -lgdi32
endif
if HAVE_WIN32
access_LTLIBRARIES += libscreen_win_plugin.la
endif
if HAVE_MAC_SCREEN
libscreen_plugin_la_SOURCES += access/screen/mac.c
libscreen_plugin_la_LDFLAGS += "-Wl,-framework,OpenGL,-framework,ApplicationServices"
libscreen_plugin_la_SOURCES = access/screen/screen.c access/screen/screen.h \
access/screen/mac.c
libscreen_plugin_la_LDFLAGS = $(AM_LDFLAGS) "-Wl,-framework,OpenGL,-framework,ApplicationServices"
access_LTLIBRARIES += libscreen_plugin.la
endif
......
/*****************************************************************************
* dxgi.cpp: Screen capture module for DXGI.
*****************************************************************************
* Copyright (C) 2018-2022 VLC authors and VideoLAN
*
* Authors: Steve Lhomme <robux4@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include "screen.h"
#include "../../video_chroma/d3d11_fmt.h"
#include <d3d11_1.h>
#include <new>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
struct screen_data_t
{
const d3d_format_t *output_format = nullptr;
vlc_video_context *vctx = nullptr;
int screen_x = 0;
int screen_y = 0;
ComPtr<IDXGIOutputDuplication> duplication;
~screen_data_t()
{
if (vctx)
vlc_video_context_Release(vctx);
}
};
static void CaptureBlockRelease( block_t *p_block )
{
block_sys_d3d11_t *d3d11_block = D3D11BLOCK_FROM_BLOCK(p_block);
picture_Release(d3d11_block->d3d11_pic);
delete d3d11_block;
}
static block_t *screen_Capture(demux_t *p_demux)
{
demux_sys_t *p_sys = static_cast<demux_sys_t*>(p_demux->p_sys);
screen_data_t *p_data = p_sys->p_data;
block_sys_d3d11_t *d3d11_block = new (std::nothrow) block_sys_d3d11_t();
ComPtr<IDXGIResource> resource;
ComPtr<ID3D11Resource> d3d11res;
picture_sys_d3d11_t *pic_sys;
D3D11_BOX copyBox;
if( unlikely(d3d11_block == nullptr) )
return nullptr;
d3d11_decoder_device_t *d3d_dev = GetD3D11OpaqueContext(p_data->vctx);
static const struct vlc_frame_callbacks cbs = {
CaptureBlockRelease,
};
block_Init( &d3d11_block->self, &cbs, nullptr, 1 );
d3d11_block->d3d11_pic = D3D11_AllocPicture(VLC_OBJECT(p_demux),
&p_sys->fmt.video, p_data->vctx,
true, p_data->output_format);
if ( d3d11_block->d3d11_pic == nullptr )
{
msg_Err(p_demux, "Failed to allocate the output texture");
goto error;
}
DXGI_OUTDUPL_FRAME_INFO frameInfo;
HRESULT hr;
hr = p_data->duplication->AcquireNextFrame(1000, &frameInfo, &resource);
if (FAILED(hr))
{
msg_Err(p_demux, "Failed to capture a frame. (hr=0x%lX)", hr);
goto error;
}
#if defined(SCREEN_SUBSCREEN) && !defined(VLC_WINSTORE_APP)
if( p_sys->b_follow_mouse )
{
POINT pos;
GetCursorPos( &pos );
pos.x -= p_data->screen_x;
pos.y -= p_data->screen_y;
FollowMouse( p_sys, pos.x, pos.y );
}
#endif // SCREEN_SUBSCREEN && !VLC_WINSTORE_APP
/* copy the texture into the block texture */
hr = resource.As(&d3d11res);
if (unlikely(FAILED(hr)))
{
msg_Err(p_demux, "Failed to get the texture. (hr=0x%lX)", hr);
goto error;
}
pic_sys = ActiveD3D11PictureSys(d3d11_block->d3d11_pic);
#ifdef SCREEN_SUBSCREEN
copyBox.left = p_sys->i_left;
copyBox.right = copyBox.left + p_sys->i_width;
copyBox.top = p_sys->i_top;
copyBox.bottom = copyBox.top + p_sys->i_height;
#else // !SCREEN_SUBSCREEN
copyBox.left = 0;
copyBox.right = p_sys->fmt.video.i_width;
copyBox.top = 0;
copyBox.bottom = p_sys->fmt.video.i_height;
#endif // !SCREEN_SUBSCREEN
copyBox.front = 0;
copyBox.back = 1;
d3d11_device_lock( &d3d_dev->d3d_dev );
d3d_dev->d3d_dev.d3dcontext->CopySubresourceRegion(
pic_sys->resource[KNOWN_DXGI_INDEX], 0,
0, 0, 0,
d3d11res.Get(), 0,
&copyBox);
p_data->duplication->ReleaseFrame();
// TODO mouse blending
d3d11_device_unlock( &d3d_dev->d3d_dev );
return &d3d11_block->self;
error:
if (d3d11_block->d3d11_pic)
picture_Release(d3d11_block->d3d11_pic);
delete d3d11_block;
return nullptr;
}
static void screen_CloseCapture(screen_data_t *p_data)
{
delete p_data;
}
int screen_InitCaptureDXGI(demux_t *p_demux)
{
demux_sys_t *p_sys = static_cast<demux_sys_t*>(p_demux->p_sys);
screen_data_t *p_data;
vlc_decoder_device *dec_dev;
HRESULT hr;
if (var_CreateGetInteger( p_demux, "screen-fragment-size" ) != 0)
{
msg_Dbg(p_demux, "screen-fragment-size not supported in DXGI");
return VLC_ENOTSUP;
}
char *mousefile = var_InheritString( p_demux, "screen-mouse-image" );
free( mousefile );
if (mousefile)
{
msg_Dbg(p_demux, "screen-mouse-image not supported in DXGI");
return VLC_ENOTSUP;
}
#ifdef VLC_WINSTORE_APP
if (p_sys->b_follow_mouse)
{
msg_Dbg(p_demux, "screen-follow-mouse not supported in UWP DXGI");
return VLC_ENOTSUP;
}
#endif // VLC_WINSTORE_APP
p_data = new (std::nothrow) screen_data_t();
if (unlikely(p_data == nullptr))
return VLC_ENOMEM;
#ifndef VLC_WINSTORE_APP
p_data->screen_x = GetSystemMetrics( SM_XVIRTUALSCREEN );
p_data->screen_y = GetSystemMetrics( SM_YVIRTUALSCREEN );
#endif
dec_dev = vlc_decoder_device_Create(VLC_OBJECT(p_demux), nullptr);
d3d11_decoder_device_t *d3d11_dev = GetD3D11OpaqueDevice(dec_dev);
if (d3d11_dev == nullptr)
{
msg_Err(p_demux, "incompatible decoder device.");
}
else
{
ComPtr<ID3D11Device1> d3d11VLC1;
hr = d3d11_dev->d3d_dev.d3ddevice->QueryInterface(IID_GRAPHICS_PPV_ARGS(&d3d11VLC1));
if (FAILED(hr)) {
msg_Warn(p_demux, "D3D11 device cannot share textures. (hr=0x%lX)", hr);
goto error;
}
ComPtr<IDXGIDevice> pDXGIDevice;
HRESULT hr = d3d11_dev->d3d_dev.d3ddevice->QueryInterface(IID_GRAPHICS_PPV_ARGS(&pDXGIDevice));
if (FAILED(hr)) {
goto error;
}
ComPtr<IDXGIAdapter> adapter;
hr = pDXGIDevice->GetAdapter(&adapter);
if (FAILED(hr)) {
goto error;
}
ComPtr<IDXGIOutput1> output1;
for (UINT j=0; output1.Get()==nullptr; j++)
{
ComPtr<IDXGIOutput> output;
hr = adapter->EnumOutputs(j, &output);
if (FAILED(hr))
break;
hr = output.As(&output1);
if (FAILED(hr))
continue;
hr = output1->DuplicateOutput(d3d11_dev->d3d_dev.d3ddevice, &p_data->duplication);
if (FAILED(hr))
output1.Reset();
}
}
if (!p_data->duplication)
goto error;
DXGI_OUTDUPL_DESC outDesc;
p_data->duplication->GetDesc(&outDesc);
for (p_data->output_format = DxgiGetRenderFormatList();
p_data->output_format->name != nullptr; ++p_data->output_format)
{
if (p_data->output_format->formatTexture == outDesc.ModeDesc.Format &&
is_d3d11_opaque(p_data->output_format->fourcc))
break;
}
if (unlikely(!p_data->output_format->name))
{
msg_Err(p_demux, "Unknown texture format %d", outDesc.ModeDesc.Format);
goto error;
}
p_data->vctx = D3D11CreateVideoContext(dec_dev, p_data->output_format->formatTexture);
vlc_decoder_device_Release(dec_dev);
dec_dev = nullptr;
if (unlikely(p_data->vctx == nullptr))
goto error;
es_format_Init( &p_sys->fmt, VIDEO_ES, p_data->output_format->fourcc );
p_sys->fmt.video.i_visible_width =
p_sys->fmt.video.i_width = outDesc.ModeDesc.Width;
p_sys->fmt.video.i_visible_height =
p_sys->fmt.video.i_height = outDesc.ModeDesc.Height;
p_sys->fmt.video.i_bits_per_pixel = 4 * p_data->output_format->bitsPerChannel; /* FIXME */
p_sys->fmt.video.i_sar_num = p_sys->fmt.video.i_sar_den = 1;
p_sys->fmt.video.i_chroma = p_sys->fmt.i_codec;
p_sys->fmt.video.color_range = COLOR_RANGE_FULL;
p_sys->fmt.video.i_frame_rate = outDesc.ModeDesc.RefreshRate.Numerator;
p_sys->fmt.video.i_frame_rate_base = outDesc.ModeDesc.RefreshRate.Denominator;
DxgiFormatMask( outDesc.ModeDesc.Format, &p_sys->fmt.video );
p_sys->p_data = p_data;
static const screen_capture_operations ops = {
screen_Capture, screen_CloseCapture,
};
p_sys->ops = &ops;
return VLC_SUCCESS;
error:
if (dec_dev)
vlc_decoder_device_Release(dec_dev);
delete p_data;
return VLC_EGENERIC;
}
int screen_InitCapture(demux_t *p_demux)
{
int ret = screen_InitCaptureDXGI(p_demux);
if (ret == VLC_SUCCESS)
return VLC_SUCCESS;
#if defined(_WIN32) && !defined(VLC_WINSTORE_APP)
return screen_InitCaptureGDI(p_demux);
#else
return ret;
#endif
}
......@@ -42,6 +42,10 @@
extern int CGSMainConnectionID();
extern CGImageRef CGSCreateRegisteredCursorImage(int, char*, CGPoint*);
static void screen_CloseCapture(screen_data_t *);
static block_t *screen_Capture(demux_t *);
struct screen_data_t
{
block_t *p_block;
......@@ -69,11 +73,16 @@ int screen_InitCapture(demux_t *p_demux)
demux_sys_t *p_sys = p_demux->p_sys;
screen_data_t *p_data;
CGLError returnedError;
unsigned int i_display_id;
unsigned int i_screen_index;
p_sys->p_data = p_data = calloc(1, sizeof(screen_data_t));
if (!p_data)
return VLC_ENOMEM;
i_display_id = var_CreateGetInteger( p_demux, "screen-display-id" );
i_screen_index = var_CreateGetInteger( p_demux, "screen-index" );
/* fetch the screen we should capture */
p_data->display_id = kCGDirectMainDisplay;
p_data->rate = var_InheritFloat(p_demux, "screen-fps");
......@@ -85,15 +94,15 @@ int screen_InitCapture(demux_t *p_demux)
ids = vlc_alloc(displayCount, sizeof(CGDirectDisplayID));
returnedError = CGGetOnlineDisplayList(displayCount, ids, &displayCount);
if (!returnedError) {
if (p_sys->i_display_id > 0) {
if (i_display_id > 0) {
for (unsigned int i = 0; i < displayCount; i++) {
if (p_sys->i_display_id == ids[i]) {
if (i_display_id == ids[i]) {
p_data->display_id = ids[i];
break;
}
}
} else if (p_sys->i_screen_index > 0 && p_sys->i_screen_index <= displayCount)
p_data->display_id = ids[p_sys->i_screen_index - 1];
} else if (i_screen_index > 0 && i_screen_index <= displayCount)
p_data->display_id = ids[i_screen_index - 1];
}
free(ids);
}
......@@ -105,9 +114,12 @@ int screen_InitCapture(demux_t *p_demux)
p_data->screen_width = rect.size.width;
p_data->screen_height = rect.size.height;
#ifdef SCREEN_SUBSCREEN
p_data->width = p_sys->i_width;
p_data->height = p_sys->i_height;
if (p_data->width <= 0 || p_data->height <= 0) {
if (p_data->width <= 0 || p_data->height <= 0)
#endif
{
p_data->width = p_data->screen_width;
p_data->height = p_data->screen_height;
}
......@@ -128,14 +140,16 @@ int screen_InitCapture(demux_t *p_demux)
p_sys->fmt.video.i_frame_rate = 1000 * p_data->rate;
p_sys->fmt.video.i_frame_rate_base = 1000;
static const struct screen_capture_operations ops = {
screen_Capture, screen_CloseCapture,
};
p_sys->ops = &ops;
return VLC_SUCCESS;
}
int screen_CloseCapture(demux_t *p_demux)
static static void screen_CloseCapture(screen_data_t *p_data)
{
demux_sys_t *p_sys = p_demux->p_sys;
screen_data_t *p_data = p_sys->p_data;
if (p_data->offscreen_context)
CFRelease(p_data->offscreen_context);
......@@ -146,8 +160,6 @@ int screen_CloseCapture(demux_t *p_demux)
block_Release(p_data->p_block);
free(p_data);
return VLC_SUCCESS;
}
block_t *screen_Capture(demux_t *p_demux)
......@@ -168,11 +180,16 @@ block_t *screen_Capture(demux_t *p_demux)
cursor_pos.x -= p_data->screen_left;
cursor_pos.y -= p_data->screen_top;
#ifdef SCREEN_SUBSCREEN
if (p_sys->b_follow_mouse)
FollowMouse(p_sys, cursor_pos.x, cursor_pos.y);
capture_rect.origin.x = p_sys->i_left;
capture_rect.origin.y = p_sys->i_top;
#else // !SCREEN_SUBSCREEN
capture_rect.origin.x = 0;
capture_rect.origin.y = 0;
#endif // !SCREEN_SUBSCREEN
capture_rect.size.width = p_data->width;
capture_rect.size.height = p_data->height;
......@@ -219,9 +236,15 @@ block_t *screen_Capture(demux_t *p_demux)
CGRect cursor_rect;
cursor_rect.size.width = CGImageGetWidth(cursor_image);
cursor_rect.size.height = CGImageGetHeight(cursor_image);
#ifdef SCREEN_SUBSCREEN
cursor_rect.origin.x = cursor_pos.x - p_sys->i_left - outHotSpot.x;
cursor_rect.origin.y = p_data->offscreen_rect.size.height
- (cursor_pos.y + cursor_rect.size.height - p_sys->i_top - outHotSpot.y);
#else // !SCREEN_SUBSCREEN
cursor_rect.origin.x = cursor_pos.x - outHotSpot.x;
cursor_rect.origin.y = p_data->offscreen_rect.size.height
- (cursor_pos.y + cursor_rect.size.height - outHotSpot.y);
#endif // !SCREEN_SUBSCREEN
CGContextDrawImage(p_data->offscreen_context, p_data->offscreen_rect, image);
CGContextDrawImage(p_data->offscreen_context, cursor_rect, cursor_image);
......
......@@ -35,6 +35,9 @@
#include <vlc_filter.h>
#include <vlc_url.h>
#include "screen.h"
#ifdef SCREEN_MOUSE
# include <vlc_image.h>
#endif
/*****************************************************************************
* Module descriptor
......@@ -75,7 +78,7 @@
"capture." )
#endif
#ifdef SCREEN_DISPLAY_ID
#ifdef __APPLE__
#define DISPLAY_ID_TEXT N_( "Display ID" )
#define DISPLAY_ID_LONGTEXT N_( \
"Display ID. If not specified, main display ID is used." )
......@@ -118,7 +121,7 @@ vlc_module_begin ()
add_integer( "screen-fragment-size", 0, FRAGS_TEXT, FRAGS_LONGTEXT )
#endif
#ifdef SCREEN_DISPLAY_ID
#ifdef __APPLE__
add_integer( "screen-display-id", 0, DISPLAY_ID_TEXT, DISPLAY_ID_LONGTEXT )
add_integer( "screen-index", 0, INDEX_TEXT, INDEX_LONGTEXT )
#endif
......@@ -163,11 +166,6 @@ static int Open( vlc_object_t *p_this )
p_sys->i_height = var_CreateGetInteger( p_demux, "screen-height" );
#endif
#ifdef SCREEN_DISPLAY_ID
p_sys->i_display_id = var_CreateGetInteger( p_demux, "screen-display-id" );
p_sys->i_screen_index = var_CreateGetInteger( p_demux, "screen-index" );
#endif
if( screen_InitCapture( p_demux ) != VLC_SUCCESS )
{
free( p_sys );
......@@ -256,16 +254,11 @@ static void Close( vlc_object_t *p_this )
demux_t *p_demux = (demux_t*)p_this;
demux_sys_t *p_sys = p_demux->p_sys;
screen_CloseCapture( p_demux );
if (p_sys->ops)
p_sys->ops->close( p_sys->p_data );
#ifdef SCREEN_MOUSE
if( p_sys->p_mouse )
picture_Release( p_sys->p_mouse );
if( p_sys->p_blend )
{
filter_Close( p_sys->p_blend );
module_unneed( p_sys->p_blend, p_sys->p_blend->p_module );
vlc_object_delete(p_sys->p_blend);
}
#endif
free( p_sys );
}
......@@ -281,17 +274,22 @@ static int Demux( demux_t *p_demux )
if( !p_sys->i_next_date ) p_sys->i_next_date = vlc_tick_now();
/* Frame skipping if necessary */
while( vlc_tick_now() >= p_sys->i_next_date + p_sys->i_incr )
p_sys->i_next_date += p_sys->i_incr;
int64_t extra_frames;
extra_frames = (vlc_tick_now() - p_sys->i_next_date) / p_sys->i_incr;
p_sys->i_next_date += extra_frames * p_sys->i_incr;
vlc_tick_wait( p_sys->i_next_date );
p_block = screen_Capture( p_demux );
p_block = p_sys->ops->capture( p_demux );
if( !p_block )
{
p_sys->i_next_date += p_sys->i_incr;
return 1;
}
// ensure the output DTS matches our ticks if the capture took too long
extra_frames = (vlc_tick_now() - p_sys->i_next_date) / p_sys->i_incr;
p_sys->i_next_date += extra_frames * p_sys->i_incr;
p_block->i_dts = p_block->i_pts = p_sys->i_next_date;
es_out_SetPCR( p_demux->out, p_block->i_pts );
......@@ -350,66 +348,3 @@ void FollowMouse( demux_sys_t *p_sys, int i_x, int i_y )
p_sys->i_screen_height - p_sys->i_height );
}
#endif
#ifdef SCREEN_MOUSE
void RenderCursor( demux_t *p_demux, int i_x, int i_y,
uint8_t *p_dst )
{
demux_sys_t *p_sys = p_demux->p_sys;
if( !p_sys->dst.i_planes )
picture_Setup( &p_sys->dst, &p_sys->fmt.video );
if( !p_sys->dst.i_planes )
return;
#ifdef _WIN32
/* Bitmaps here created by CreateDIBSection: stride rounded up to the nearest DWORD */
p_sys->dst.p[ 0 ].i_pitch = p_sys->dst.p[ 0 ].i_visible_pitch =
( ( ( ( p_sys->fmt.video.i_width * p_sys->fmt.video.i_bits_per_pixel ) + 31 ) & ~31 ) >> 3 );
#endif
if( !p_sys->p_blend )
{
p_sys->p_blend = vlc_object_create( p_demux, sizeof(filter_t) );
if( p_sys->p_blend )
{
es_format_Init( &p_sys->p_blend->fmt_in, VIDEO_ES,
VLC_CODEC_RGBA );
p_sys->p_blend->fmt_in.video = p_sys->p_mouse->format;
p_sys->p_blend->fmt_out = p_sys->fmt;
p_sys->p_blend->p_module =
module_need( p_sys->p_blend, "video blending", NULL, false );
if( !p_sys->p_blend->p_module )
{
msg_Err( p_demux, "Could not load video blending module" );
vlc_object_delete(p_sys->p_blend);
p_sys->p_blend = NULL;
}
assert( p_sys->p_blend->ops != NULL );
}
}
if( p_sys->p_blend )
{
p_sys->dst.p->p_pixels = p_dst;
p_sys->p_blend->ops->blend_video( p_sys->p_blend,
&p_sys->dst,
p_sys->p_mouse,
#ifdef SCREEN_SUBSCREEN
i_x-p_sys->i_left,
#else
i_x,
#endif
#ifdef SCREEN_SUBSCREEN
i_y-p_sys->i_top,
#else
i_y,
#endif
255 );
}
else
{
picture_Release( p_sys->p_mouse );
p_sys->p_mouse = NULL;
}
}
#endif
......@@ -25,19 +25,23 @@
#include <vlc_access.h>
#include <vlc_demux.h>
#ifdef __APPLE__
# define SCREEN_DISPLAY_ID
#endif
#define SCREEN_SUBSCREEN
#ifdef _WIN32
#define SCREEN_MOUSE
#endif
#ifdef SCREEN_MOUSE
# include <vlc_image.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct screen_data_t screen_data_t;
struct screen_capture_operations
{
block_t* (*capture)( demux_t * );
void (*close)( screen_data_t * );
};
typedef struct
{
es_format_t fmt;
......@@ -62,25 +66,22 @@ typedef struct
#ifdef SCREEN_MOUSE
picture_t *p_mouse;
filter_t *p_blend;
picture_t dst;
#endif
#ifdef SCREEN_DISPLAY_ID
unsigned int i_display_id;
unsigned int i_screen_index;
#endif
screen_data_t *p_data;
const struct screen_capture_operations *ops;
} demux_sys_t;
int screen_InitCapture ( demux_t * );
int screen_CloseCapture( demux_t * );
block_t *screen_Capture( demux_t * );
#if defined(_WIN32) && !defined(VLC_WINSTORE_APP)
int screen_InitCaptureGDI ( demux_t * );
#endif
#ifdef SCREEN_SUBSCREEN
void FollowMouse( demux_sys_t *, int, int );
#endif
#ifdef SCREEN_MOUSE
void RenderCursor( demux_t *, int, int, uint8_t * );
#ifdef __cplusplus
}
#endif
......@@ -29,9 +29,16 @@
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_modules.h> /* module_need for "video blending" */
#include <vlc_filter.h>
#include "screen.h"
static void screen_CloseCapture(screen_data_t *);
static block_t *screen_Capture(demux_t *);
struct screen_data_t
{
HDC hdc_src;
......@@ -44,8 +51,13 @@ struct screen_data_t
int i_fragment_size;
int i_fragment;
block_t *p_block;
#ifdef SCREEN_MOUSE
filter_t *p_blend;
#endif
};
#if defined(SCREEN_SUBSCREEN) || defined(SCREEN_MOUSE)
/*
* In screen coordinates the origin is the upper-left corner of the primary
* display, and points can have negative x/y when other displays are located
......@@ -69,7 +81,9 @@ static inline void FromScreenCoordinates( demux_t *p_demux, POINT *p_point )
p_point->x += p_data->ptl.x;
p_point->y += p_data->ptl.y;
}
#endif
#if defined(SCREEN_SUBSCREEN)
static inline void ToScreenCoordinates( demux_t *p_demux, POINT *p_point )
{
demux_sys_t *p_sys = p_demux->p_sys;
......@@ -77,8 +91,9 @@ static inline void ToScreenCoordinates( demux_t *p_demux, POINT *p_point )
p_point->x -= p_data->ptl.x;
p_point->y -= p_data->ptl.y;
}
#endif
int screen_InitCapture( demux_t *p_demux )
int screen_InitCaptureGDI( demux_t *p_demux )
{
demux_sys_t *p_sys = p_demux->p_sys;
screen_data_t *p_data;
......@@ -162,14 +177,16 @@ int screen_InitCapture( demux_t *p_demux )
p_data->ptl.x = - GetSystemMetrics( SM_XVIRTUALSCREEN );
p_data->ptl.y = - GetSystemMetrics( SM_YVIRTUALSCREEN );
static const struct screen_capture_operations ops = {
screen_Capture, screen_CloseCapture,
};
p_sys->ops = &ops;
return VLC_SUCCESS;
}
int screen_CloseCapture( demux_t *p_demux )
void screen_CloseCapture( screen_data_t *p_data )
{
demux_sys_t *p_sys = p_demux->p_sys;
screen_data_t *p_data = p_sys->p_data;
if( p_data->p_block ) block_Release( p_data->p_block );
if( p_data->hgdi_backup)
......@@ -177,9 +194,17 @@ int screen_CloseCapture( demux_t *p_demux )
DeleteDC( p_data->hdc_dst );
ReleaseDC( 0, p_data->hdc_src );
free( p_data );
return VLC_SUCCESS;
#ifdef SCREEN_MOUSE
if( p_data->p_blend )
{
filter_Close( p_data->p_blend );
module_unneed( p_data->p_blend, p_data->p_blend->p_module );
vlc_object_delete(p_data->p_blend);
}
#endif
free( p_data );
}
struct block_sys_t
......@@ -275,6 +300,65 @@ error:
return NULL;
}
#ifdef SCREEN_MOUSE
static void RenderCursor( demux_t *p_demux, int i_x, int i_y,
uint8_t *p_dst )
{
demux_sys_t *p_sys = p_demux->p_sys;
screen_data_t *p_data = p_sys->p_data;
if( !p_sys->dst.i_planes )
picture_Setup( &p_sys->dst, &p_sys->fmt.video );
if( !p_sys->dst.i_planes )
return;
/* Bitmaps here created by CreateDIBSection: stride rounded up to the nearest DWORD */
p_sys->dst.p[ 0 ].i_pitch = p_sys->dst.p[ 0 ].i_visible_pitch =
( ( ( ( p_sys->fmt.video.i_width * p_sys->fmt.video.i_bits_per_pixel ) + 31 ) & ~31 ) >> 3 );
if( !p_data->p_blend )
{
p_data->p_blend = vlc_object_create( p_demux, sizeof(filter_t) );
if( p_data->p_blend )
{
es_format_Init( &p_data->p_blend->fmt_in, VIDEO_ES,
VLC_CODEC_RGBA );
p_data->p_blend->fmt_in.video = p_sys->p_mouse->format;
p_data->p_blend->fmt_out = p_sys->fmt;
p_data->p_blend->p_module =
module_need( p_data->p_blend, "video blending", NULL, false );
if( !p_data->p_blend->p_module )
{
msg_Err( p_demux, "Could not load video blending module" );
vlc_object_delete(p_data->p_blend);
p_data->p_blend = NULL;
picture_Release( p_sys->p_mouse );
p_sys->p_mouse = NULL;
}
assert( p_data->p_blend->ops != NULL );
}
}
if( p_data->p_blend )
{
p_sys->dst.p->p_pixels = p_dst;
p_data->p_blend->ops->blend_video( p_data->p_blend,
&p_sys->dst,
p_sys->p_mouse,
#ifdef SCREEN_SUBSCREEN
i_x-p_sys->i_left,
#else
i_x,
#endif
#ifdef SCREEN_SUBSCREEN
i_y-p_sys->i_top,
#else
i_y,
#endif
255 );
}
}
#endif
block_t *screen_Capture( demux_t *p_demux )
{
demux_sys_t *p_sys = p_demux->p_sys;
......@@ -289,16 +373,24 @@ block_t *screen_Capture( demux_t *p_demux )
}
}
POINT pos;
#if defined(SCREEN_SUBSCREEN) || defined(SCREEN_MOUSE)
GetCursorPos( &pos );
FromScreenCoordinates( p_demux, &pos );
#endif // SCREEN_SUBSCREEN || SCREEN_MOUSE
#if defined(SCREEN_SUBSCREEN)
if( p_sys->b_follow_mouse )
{
POINT pos;
GetCursorPos( &pos );
FromScreenCoordinates( p_demux, &pos );
FollowMouse( p_sys, pos.x, pos.y );
}
#endif // SCREEN_SUBSCREEN
#if defined(SCREEN_SUBSCREEN)
POINT top_left = { p_sys->i_left, p_sys->i_top };
ToScreenCoordinates( p_demux, &top_left );
#else // !SCREEN_SUBSCREEN
POINT top_left = { 0, 0 };
#endif // !SCREEN_SUBSCREEN
if( !BitBlt( p_data->hdc_dst, 0,
p_data->i_fragment * p_data->i_fragment_size,
......@@ -320,6 +412,7 @@ block_t *screen_Capture( demux_t *p_demux )
p_data->i_fragment = 0;
p_data->p_block = 0;
#ifdef SCREEN_MOUSE
if( p_sys->p_mouse )
{
POINT pos;
......@@ -329,6 +422,7 @@ block_t *screen_Capture( demux_t *p_demux )
RenderCursor( p_demux, pos.x, pos.y,
p_block->p_buffer );
}
#endif
return p_block;
}
......
......@@ -3,6 +3,7 @@ d3d11dir = $(pluginsdir)/d3d11
libdirect3d11_filters_plugin_la_SOURCES = hw/d3d11/d3d11_filters.h \
hw/d3d11/d3d11_filters.c \
hw/d3d11/d3d11_deinterlace.c \
hw/d3d11/d3d11_decoder.cpp \
hw/d3d11/d3d11_device.c \
hw/d3d11/d3d11_surface.c \
hw/d3d11/d3d11_processor.c hw/d3d11/d3d11_processor.h
......
/*****************************************************************************
* d3d11_decoder.cpp : D3D11 GPU block to picture decoder
*****************************************************************************
* Copyright © 2018-2022 VLC authors, VideoLAN and VideoLabs
*
* Authors: Steve Lhomme <robux4@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_codec.h>
#include <vlc_picture.h>
#include <vlc_modules.h>
#include "d3d11_filters.h"
#include <dxgi1_2.h>
#include <d3d11_1.h>
#include <new>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
struct d3d11_dec_sys {
date_t pts;
const d3d_format_t *output_format = nullptr;
vlc_video_context *vctx = nullptr;
vlc_decoder_device *dec_dev = nullptr;
~d3d11_dec_sys()
{
if (vctx)
vlc_video_context_Release(vctx);
if (dec_dev)
vlc_decoder_device_Release(dec_dev);
}
};
static block_t *DecodeBlock( decoder_t *p_dec, block_t *p_block )
{
d3d11_dec_sys *p_sys = static_cast<d3d11_dec_sys*>(p_dec->p_sys);
if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) )
{
date_Set( &p_sys->pts, p_block->i_dts );
if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
{
block_Release( p_block );
return nullptr;
}
}
if( p_block->i_pts <= VLC_TICK_INVALID && p_block->i_dts <= VLC_TICK_INVALID &&
!date_Get( &p_sys->pts ) )
{
/* We've just started the stream, wait for the first PTS. */
block_Release( p_block );
return nullptr;
}
/* Date management: If there is a pts avaliable, use that. */
if( p_block->i_pts > VLC_TICK_INVALID )
{
date_Set( &p_sys->pts, p_block->i_pts );
}
else if( p_block->i_dts > VLC_TICK_INVALID )
{
/* NB, davidf doesn't quite agree with this in general, it is ok
* for rawvideo since it is in order (ie pts=dts), however, it
* may not be ok for an out-of-order codec, so don't copy this
* without thinking */
date_Set( &p_sys->pts, p_block->i_dts );
}
return p_block;
}
static int DecodeFrame( decoder_t *p_dec, block_t *p_block )
{
if( p_block == nullptr ) // No Drain needed
return VLCDEC_SUCCESS;
p_block = DecodeBlock( p_dec, p_block );
if( p_block == nullptr )
return VLCDEC_SUCCESS;
HRESULT hr;
ComPtr<ID3D11Resource> d3d11res;
d3d11_dec_sys *p_sys = static_cast<d3d11_dec_sys*>(p_dec->p_sys);
picture_t *p_pic = D3D11BLOCK_FROM_BLOCK(p_block)->d3d11_pic;
assert( p_pic != nullptr );
picture_sys_d3d11_t *src_sys = ActiveD3D11PictureSys(p_pic);
if (unlikely(p_sys->output_format == nullptr))
{
D3D11_TEXTURE2D_DESC outDesc;
src_sys->texture[0]->GetDesc(&outDesc);
for (p_sys->output_format = DxgiGetRenderFormatList();
p_sys->output_format->name != nullptr; ++p_sys->output_format)
{
if (p_sys->output_format->formatTexture == outDesc.Format &&
is_d3d11_opaque(p_sys->output_format->fourcc))
break;
}
if (unlikely(!p_sys->output_format->name))
{
msg_Err(p_dec, "Unknown texture format %d", outDesc.Format);
block_Release( p_block );
return VLC_EGENERIC;
}
}
if (unlikely(p_sys->vctx == nullptr))
{
p_sys->vctx =
D3D11CreateVideoContext(p_sys->dec_dev, p_sys->output_format->formatTexture);
if (!p_sys->vctx)
{
block_Release( p_block );
return VLC_EGENERIC;
}
if( decoder_UpdateVideoOutput( p_dec, p_sys->vctx ) != VLC_SUCCESS )
{
block_Release( p_block );
return VLCDEC_SUCCESS;
}
}
p_pic->date = date_Get( &p_sys->pts );
date_Increment( &p_sys->pts, 1 );
if( p_block->i_flags & BLOCK_FLAG_INTERLACED_MASK )
{
p_pic->b_progressive = false;
p_pic->i_nb_fields = (p_block->i_flags & BLOCK_FLAG_SINGLE_FIELD) ? 1 : 2;
if( p_block->i_flags & BLOCK_FLAG_TOP_FIELD_FIRST )
p_pic->b_top_field_first = true;
else
p_pic->b_top_field_first = false;
}
else
p_pic->b_progressive = true;
// replace the texture shared the DXGI device by a texture for our device
assert(src_sys->sharedHandle != INVALID_HANDLE_VALUE);
assert(src_sys->processorInput == nullptr);
assert(src_sys->processorOutput == nullptr);
assert(src_sys->texture[1] == nullptr);
d3d11_decoder_device_t *dev_sys = GetD3D11OpaqueDevice(p_sys->dec_dev);
ComPtr<ID3D11Device1> d3d11VLC1;
dev_sys->d3d_dev.d3ddevice->QueryInterface(IID_GRAPHICS_PPV_ARGS(&d3d11VLC1));
picture_sys_d3d11_t *pic_sys = ActiveD3D11PictureSys(p_pic);
ID3D11Texture2D* sharedTex;
hr = d3d11VLC1->OpenSharedResource1(pic_sys->sharedHandle, IID_GRAPHICS_PPV_ARGS(&sharedTex));
ID3D11Texture2D *srcTex = src_sys->texture[0];
auto *srcVctx = p_pic->context->vctx;
src_sys->texture[0] = sharedTex;
p_pic->context->vctx = vlc_video_context_Hold(p_sys->vctx);
srcTex->Release();
vlc_video_context_Release(srcVctx);
for (int j = 0; j < DXGI_MAX_SHADER_VIEW; j++)
{
if (src_sys->renderSrc[j])
src_sys->renderSrc[j]->Release();
}
D3D11_AllocateResourceView(p_dec, dev_sys->d3d_dev.d3ddevice, p_sys->output_format,
src_sys->texture, src_sys->slice_index, src_sys->renderSrc);
picture_Hold( p_pic ); // hold the picture we got from the block
block_Release( p_block );
decoder_QueueVideo( p_dec, p_pic );
return VLCDEC_SUCCESS;
}
static void Flush( decoder_t *p_dec )
{
d3d11_dec_sys *p_sys = static_cast<d3d11_dec_sys*>(p_dec->p_sys);
date_Set( &p_sys->pts, VLC_TICK_INVALID );
}
void D3D11CloseBlockDecoder( vlc_object_t *obj )
{
decoder_t *p_dec = (decoder_t *)obj;
d3d11_dec_sys *p_sys = static_cast<d3d11_dec_sys*>(p_dec->p_sys);
delete p_sys;
}
int D3D11OpenBlockDecoder( vlc_object_t *obj )
{
decoder_t *p_dec = (decoder_t *)obj;
if ( !is_d3d11_opaque(p_dec->fmt_in.video.i_chroma) )
return VLC_EGENERIC;
if( p_dec->fmt_in.video.i_width <= 0 || p_dec->fmt_in.video.i_height == 0 )
{
msg_Err( p_dec, "invalid display size %dx%d",
p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height );
return VLC_EGENERIC;
}
vlc_decoder_device *dec_dev = decoder_GetDecoderDevice(p_dec);
if (dec_dev == nullptr)
return VLC_ENOTSUP;
auto dev_sys = GetD3D11OpaqueDevice(dec_dev);
if (dev_sys == nullptr)
{
vlc_decoder_device_Release(dec_dev);
return VLC_ENOTSUP;
}
d3d11_dec_sys *p_sys = new (std::nothrow) d3d11_dec_sys();
if (unlikely(!p_sys))
{
vlc_decoder_device_Release(dec_dev);
return VLC_ENOMEM;
}
p_sys->dec_dev = dec_dev;
if( !p_dec->fmt_in.video.i_visible_width )
p_dec->fmt_in.video.i_visible_width = p_dec->fmt_in.video.i_width;
if( !p_dec->fmt_in.video.i_visible_height )
p_dec->fmt_in.video.i_visible_height = p_dec->fmt_in.video.i_height;
es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
if( p_dec->fmt_out.video.i_frame_rate == 0 ||
p_dec->fmt_out.video.i_frame_rate_base == 0)
{
msg_Warn( p_dec, "invalid frame rate %d/%d, using 25 fps instead",
p_dec->fmt_out.video.i_frame_rate,
p_dec->fmt_out.video.i_frame_rate_base);
date_Init( &p_sys->pts, 25, 1 );
}
else
date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate,
p_dec->fmt_out.video.i_frame_rate_base );
if (p_dec->fmt_in.video.i_chroma == VLC_CODEC_D3D11_OPAQUE_BGRA)
{
// there's only one possible value so we don't have to wait for the
// DXGI_FORMAT
for (p_sys->output_format = DxgiGetRenderFormatList();
p_sys->output_format->name != nullptr; ++p_sys->output_format)
{
if (p_sys->output_format->fourcc == p_dec->fmt_in.video.i_chroma &&
is_d3d11_opaque(p_sys->output_format->fourcc))
break;
}
p_sys->vctx =
D3D11CreateVideoContext(p_sys->dec_dev, p_sys->output_format->formatTexture);
if (!p_sys->vctx)
{
vlc_decoder_device_Release(dec_dev);
return VLC_EGENERIC;
}
if( decoder_UpdateVideoOutput( p_dec, p_sys->vctx ) != VLC_SUCCESS )
{
vlc_video_context_Release(p_sys->vctx);
vlc_decoder_device_Release(dec_dev);
return VLC_EGENERIC;
}
}
else
{
// we can't do a decoder_UpdateVideoOutput() here as we don't have the video context
// we assume the output will handle the D3D11 output
}
p_dec->pf_decode = DecodeFrame;
p_dec->pf_flush = Flush;
p_dec->p_sys = p_sys;
return VLC_SUCCESS;
}
......@@ -193,7 +193,7 @@ picture_t *AllocPicture( filter_t *p_filter )
filter_sys_t *p_sys = p_filter->p_sys;
picture_t *pic = D3D11_AllocPicture(VLC_OBJECT(p_filter), &p_filter->fmt_out.video,
p_filter->vctx_out, p_sys->output_format);
p_filter->vctx_out, false, p_sys->output_format);
if (pic == NULL)
return NULL;
......
......@@ -202,7 +202,9 @@ static picture_t *AllocPicture( filter_t *p_filter )
if (unlikely(cfg == NULL))
return NULL;
return D3D11_AllocPicture(VLC_OBJECT(p_filter), &p_filter->fmt_out.video, p_filter->vctx_out, cfg);
return D3D11_AllocPicture(VLC_OBJECT(p_filter),
&p_filter->fmt_out.video, p_filter->vctx_out,
false, cfg);
}
static picture_t *Filter(filter_t *p_filter, picture_t *p_pic)
......@@ -596,4 +598,9 @@ vlc_module_begin()
#endif /* VLC_WINSTORE_APP */
add_shortcut ("d3d11")
add_submodule()
set_subcategory( SUBCAT_INPUT_VCODEC )
set_callbacks( D3D11OpenBlockDecoder, D3D11CloseBlockDecoder )
set_capability( "video decoder", 90 )
vlc_module_end()
......@@ -28,11 +28,21 @@
#include "../../video_chroma/d3d11_fmt.h"
#ifdef __cplusplus
extern "C" {
#endif
int D3D11OpenDeinterlace(filter_t *);
int D3D11OpenConverter(filter_t *);
int D3D11OpenCPUConverter(filter_t *);
int D3D11OpenBlockDecoder(vlc_object_t *);
void D3D11CloseBlockDecoder(vlc_object_t *);
int D3D11OpenDecoderDeviceW8(vlc_decoder_device *, vout_window_t *);
int D3D11OpenDecoderDeviceAny(vlc_decoder_device *, vout_window_t *);
#ifdef __cplusplus
}
#endif
#endif /* VLC_D3D11_FILTERS_H */
......@@ -643,7 +643,7 @@ static picture_t *AllocateCPUtoGPUTexture(filter_t *p_filter, filter_sys_t *p_sy
}
if (AllocateTextures(p_filter, p_sys->d3d_dev, cfg,
&p_dst->format, pic_ctx->picsys.texture, p_dst->p) != VLC_SUCCESS)
&p_dst->format, false, pic_ctx->picsys.texture, p_dst->p) != VLC_SUCCESS)
goto done;
if (unlikely(D3D11_AllocateResourceView(p_filter, p_sys->d3d_dev->d3ddevice, cfg,
......
......@@ -38,6 +38,7 @@
#include <d3d11.h>
#include <assert.h>
#include <initguid.h>
#include <dxgi1_2.h>
#if !defined(NDEBUG) && defined(HAVE_DXGIDEBUG_H)
# include <dxgidebug.h>
#endif
......@@ -802,7 +803,7 @@ const d3d_format_t *(FindD3D11Format)(vlc_object_t *o,
#undef AllocateTextures
int AllocateTextures( vlc_object_t *obj, d3d11_device_t *d3d_dev,
const d3d_format_t *cfg, const video_format_t *fmt,
const d3d_format_t *cfg, const video_format_t *fmt, bool shared,
ID3D11Texture2D *textures[],
plane_t out_planes[] )
{
......@@ -814,7 +815,8 @@ int AllocateTextures( vlc_object_t *obj, d3d11_device_t *d3d_dev,
ZeroMemory(&texDesc, sizeof(texDesc));
texDesc.MipLevels = 1;
texDesc.SampleDesc.Count = 1;
texDesc.MiscFlags = 0; //D3D11_RESOURCE_MISC_SHARED;
if (shared)
texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texDesc.ArraySize = 1;
if (is_d3d11_opaque(fmt->i_chroma)) {
......@@ -945,6 +947,8 @@ void d3d11_pic_context_destroy(picture_context_t *ctx)
{
struct d3d11_pic_context *pic_ctx = D3D11_PICCONTEXT_FROM_PICCTX(ctx);
ReleaseD3D11PictureSys(&pic_ctx->picsys);
if (pic_ctx->picsys.sharedHandle != INVALID_HANDLE_VALUE)
CloseHandle(pic_ctx->picsys.sharedHandle);
free(pic_ctx);
}
......@@ -960,7 +964,8 @@ picture_context_t *d3d11_pic_context_copy(picture_context_t *ctx)
}
picture_t *D3D11_AllocPicture(vlc_object_t *obj,
const video_format_t *fmt, vlc_video_context *vctx_out, const d3d_format_t *cfg)
const video_format_t *fmt, vlc_video_context *vctx_out,
bool shared, const d3d_format_t *cfg)
{
if (unlikely(cfg == NULL))
return NULL;
......@@ -968,6 +973,7 @@ picture_t *D3D11_AllocPicture(vlc_object_t *obj,
struct d3d11_pic_context *pic_ctx = calloc(1, sizeof(*pic_ctx));
if (unlikely(pic_ctx == NULL))
return NULL;
pic_ctx->picsys.sharedHandle = INVALID_HANDLE_VALUE;
picture_t *pic = picture_NewFromFormat( fmt );
if (unlikely(pic == NULL))
......@@ -978,7 +984,7 @@ picture_t *D3D11_AllocPicture(vlc_object_t *obj,
d3d11_decoder_device_t *dev_sys = GetD3D11OpaqueContext(vctx_out);
if (AllocateTextures(obj, &dev_sys->d3d_dev, cfg,
fmt, pic_ctx->picsys.texture, NULL) != VLC_SUCCESS)
fmt, shared, pic_ctx->picsys.texture, NULL) != VLC_SUCCESS)
{
picture_Release(pic);
free(pic_ctx);
......@@ -987,6 +993,22 @@ picture_t *D3D11_AllocPicture(vlc_object_t *obj,
D3D11_AllocateResourceView(obj, dev_sys->d3d_dev.d3ddevice, cfg, pic_ctx->picsys.texture, 0, pic_ctx->picsys.renderSrc);
if (shared)
{
HRESULT hr;
void *pv;
IDXGIResource1 *sharedResource;
hr = ID3D11Texture2D_QueryInterface(pic_ctx->picsys.texture[0], &IID_IDXGIResource1,&pv);
if (likely(SUCCEEDED(hr)))
{
sharedResource = pv;
IDXGIResource1_CreateSharedHandle(sharedResource, NULL,
DXGI_SHARED_RESOURCE_READ/*|DXGI_SHARED_RESOURCE_WRITE*/,
NULL, &pic_ctx->picsys.sharedHandle);
IDXGIResource1_Release(sharedResource);
}
}
pic_ctx->s = (picture_context_t) {
d3d11_pic_context_destroy, d3d11_pic_context_copy,
vlc_video_context_Hold(vctx_out),
......
......@@ -75,6 +75,7 @@ typedef struct
ID3D11VideoProcessorInputView *processorInput; /* when used as processor input */
ID3D11VideoProcessorOutputView *processorOutput; /* when used as processor output */
ID3D11ShaderResourceView *renderSrc[DXGI_MAX_SHADER_VIEW];
HANDLE sharedHandle;
} picture_sys_d3d11_t;
struct d3d11_pic_context
......@@ -83,6 +84,15 @@ struct d3d11_pic_context
picture_sys_d3d11_t picsys;
};
struct block_sys_d3d11_t
{
block_t self;
picture_t *d3d11_pic;
};
#define D3D11BLOCK_FROM_BLOCK(block) \
container_of((block), struct block_sys_d3d11_t, self)
typedef struct
{
d3d11_device_t d3d_dev;
......@@ -177,9 +187,9 @@ const d3d_format_t *FindD3D11Format(vlc_object_t *,
FindD3D11Format(VLC_OBJECT(a),b,c,d,e,f,g,h,i)
int AllocateTextures(vlc_object_t *, d3d11_device_t *, const d3d_format_t *,
const video_format_t *, ID3D11Texture2D *textures[],
plane_t planes[]);
#define AllocateTextures(a,b,c,d,e,f) AllocateTextures(VLC_OBJECT(a),b,c,d,e,f)
const video_format_t *, bool, ID3D11Texture2D *textures[],
plane_t planes[]) VLC_USED;
#define AllocateTextures(a,b,c,d,e,f,g) AllocateTextures(VLC_OBJECT(a),b,c,d,e,f,g)
static inline void d3d11_device_lock(d3d11_device_t *d3d_dev)
{
......@@ -197,7 +207,8 @@ void d3d11_pic_context_destroy(picture_context_t *);
picture_context_t *d3d11_pic_context_copy(picture_context_t *);
picture_t *D3D11_AllocPicture(vlc_object_t *,
const video_format_t *, vlc_video_context *, const d3d_format_t *);
const video_format_t *, vlc_video_context *,
bool, const d3d_format_t *);
#ifdef __cplusplus
}
......
......@@ -318,7 +318,8 @@ static int UpdateStaging(vout_display_t *vd, const video_format_t *fmt)
if (!is_d3d11_opaque(fmt->i_chroma))
texture_fmt.i_chroma = sys->picQuad.generic.textureFormat->fourcc;
if (AllocateTextures(vd, sys->d3d_dev, sys->picQuad.generic.textureFormat, &texture_fmt, textures, sys->stagingPlanes))
if (AllocateTextures(vd, sys->d3d_dev, sys->picQuad.generic.textureFormat, &texture_fmt,
false, textures, sys->stagingPlanes))
{
msg_Err(vd, "Failed to allocate the staging texture");
return VLC_EGENERIC;
......@@ -1321,7 +1322,8 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
continue;
}
quad = d3dquad;
if (AllocateTextures(vd, sys->d3d_dev, sys->regionQuad.generic.textureFormat, &r->p_picture->format, d3dquad->picSys.texture, NULL)) {
if (AllocateTextures(vd, sys->d3d_dev, sys->regionQuad.generic.textureFormat, &r->p_picture->format,
false, d3dquad->picSys.texture, NULL)) {
msg_Err(vd, "Failed to allocate %dx%d texture for OSD",
r->fmt.i_visible_width, r->fmt.i_visible_height);
for (int j=0; j<DXGI_MAX_SHADER_VIEW; j++)
......