├── .github
├── issue_template.md
└── workflows
│ └── main.yml
├── .gitignore
├── .gitmodules
├── Include
├── FilterInterfaces.h
├── FilterInterfacesImpl.h
├── ID3DFullscreenControl.h
├── ID3DVideoMemoryConfiguration.h
├── IMediaSideData.h
├── ISubRender.h
├── ISubRender11.h
├── SubRenderIntf.h
└── Version.h
├── LICENSE.txt
├── MpcVideoRenderer.sln
├── Readme.md
├── Shaders
├── Shaders.vcxproj
├── Shaders.vcxproj.filters
├── compile_shaders.cmd
├── convert
│ ├── colorspace_gamut_conversion.hlsl
│ ├── conv_matrix.hlsl
│ ├── hdr_tone_mapping.hlsl
│ ├── hlg.hlsl
│ └── st2084.hlsl
├── d3d11
│ ├── ps_TEST.hlsl
│ ├── ps_convert_biplanar.hlsl
│ ├── ps_convert_bitmap_to_pq.hlsl
│ ├── ps_convert_color.hlsl
│ ├── ps_convert_hlg_to_pq.hlsl
│ ├── ps_convert_planar.hlsl
│ ├── ps_convert_planar_yv.hlsl
│ ├── ps_convert_pq_to_sdr.hlsl
│ ├── ps_convolution.hlsl
│ ├── ps_final_pass.hlsl
│ ├── ps_fix_bt2020.hlsl
│ ├── ps_fix_ycgco.hlsl
│ ├── ps_fixconvert_hlg_to_sdr.hlsl
│ ├── ps_fixconvert_pq_to_sdr.hlsl
│ ├── ps_font.hlsl
│ ├── ps_geometry.hlsl
│ ├── ps_halfoverunder_to_interlace.hlsl
│ ├── ps_interpolation_lanczos2.hlsl
│ ├── ps_interpolation_lanczos3.hlsl
│ ├── ps_interpolation_spline4.hlsl
│ ├── ps_simple.hlsl
│ ├── vs_geometry.hlsl
│ └── vs_simple.hlsl
├── d3d9
│ ├── convert_biplanar.hlsl
│ ├── convert_color.hlsl
│ ├── convert_planar.hlsl
│ ├── convert_planar_yv.hlsl
│ ├── convolution.hlsl
│ ├── final_pass.hlsl
│ ├── fix_bt2020.hlsl
│ ├── fix_ycgco.hlsl
│ ├── fixconvert_hlg_to_sdr.hlsl
│ ├── fixconvert_pq_to_sdr.hlsl
│ ├── halfoverunder_to_interlace.hlsl
│ ├── interpolation_lanczos2.hlsl
│ ├── interpolation_lanczos3.hlsl
│ └── interpolation_spline4.hlsl
├── examples
│ ├── ps_mpv.hlsl
│ ├── ps_resize_onepass_bilinear.hlsl
│ ├── ps_resize_onepass_catmull4.hlsl
│ ├── ps_resize_onepass_jinc2.hlsl
│ ├── ps_vlc.hlsl
│ ├── resizer_onepass_jinc2.hlsl
│ ├── vs_mpv.hlsl
│ └── vs_vlc.hlsl
└── resize
│ └── convolution_filters.hlsl
├── Source
├── CustomAllocator.cpp
├── CustomAllocator.h
├── D3D11VP.cpp
├── D3D11VP.h
├── D3DUtil
│ ├── D3D11Font.cpp
│ ├── D3D11Font.h
│ ├── D3D11Geometry.cpp
│ ├── D3D11Geometry.h
│ ├── D3D9Font.cpp
│ ├── D3D9Font.h
│ ├── D3D9Geometry.cpp
│ ├── D3D9Geometry.h
│ ├── D3DCommon.h
│ └── FontBitmap.h
├── DX11Helper.cpp
├── DX11Helper.h
├── DX11VideoProcessor.cpp
├── DX11VideoProcessor.h
├── DX9Helper.cpp
├── DX9Helper.h
├── DX9VideoProcessor.cpp
├── DX9VideoProcessor.h
├── DXVA2VP.cpp
├── DXVA2VP.h
├── DisplayConfig.cpp
├── DisplayConfig.h
├── FrameStats.h
├── Helper.cpp
├── Helper.h
├── IVideoRenderer.h
├── MediaSampleSideData.cpp
├── MediaSampleSideData.h
├── MpcVideoRenderer.def
├── MpcVideoRenderer.rc
├── MpcVideoRenderer.vcxproj
├── MpcVideoRenderer.vcxproj.filters
├── PropPage.cpp
├── PropPage.h
├── Shaders.cpp
├── Shaders.h
├── SubPic
│ ├── DX11SubPic.cpp
│ ├── DX11SubPic.h
│ ├── DX9SubPic.cpp
│ ├── DX9SubPic.h
│ ├── ISubPic.h
│ ├── SubPicImpl.cpp
│ ├── SubPicImpl.h
│ ├── SubPicQueueImpl.cpp
│ ├── SubPicQueueImpl.h
│ ├── XySubPicProvider.cpp
│ ├── XySubPicProvider.h
│ ├── XySubPicQueueImpl.cpp
│ └── XySubPicQueueImpl.h
├── Times.cpp
├── Times.h
├── Utils
│ ├── CPUInfo.cpp
│ ├── CPUInfo.h
│ ├── StringUtil.cpp
│ ├── StringUtil.h
│ ├── Util.cpp
│ ├── Util.h
│ └── gpu_memcpy_sse4.h
├── VideoProcessor.cpp
├── VideoProcessor.h
├── VideoRenderer.cpp
├── VideoRenderer.h
├── VideoRendererInputPin.cpp
├── VideoRendererInputPin.h
├── csputils.cpp
├── csputils.h
├── dllmain.cpp
├── renbase2.cpp
├── renbase2.h
├── res
│ ├── MpcVideoRenderer.rc2
│ └── dither32x32float16.bin
├── resource.h
├── stdafx.cpp
└── stdafx.h
├── build_mpcvr.cmd
├── common.props
├── distrib
├── Install_MPCVR_32.cmd
├── Install_MPCVR_64.cmd
├── Reset_Settings.cmd
├── Uninstall_MPCVR_32.cmd
└── Uninstall_MPCVR_64.cmd
├── external
├── BaseClasses.vcxproj
├── BaseClasses.vcxproj.filters
├── minhook.vcxproj
└── minhook.vcxproj.filters
├── history.txt
├── platform.props
├── sign.cmd
├── update_revision.cmd
└── update_submodules.cmd
/.github/issue_template.md:
--------------------------------------------------------------------------------
1 | ### Prerequisites
2 |
3 | * [ ] Are you running the [latest version](https://github.com/Aleksoid1978/VideoRenderer/releases/latest)?
4 | * [ ] Are you running the [latest "nightly" builds](https://github.com/qwerttvv/Player/releases)?
5 | * [ ] Have you read [Known Issues](Known-Issues)?
6 |
7 |
8 | ### Description
9 |
10 | [Description of the bug or feature]
11 |
12 |
13 | ### Steps to Reproduce the Problem
14 |
15 | 1.
16 | 1.
17 | 1.
18 |
19 | ### Video files for testing
20 |
21 | [Link to video file to reproduce the problem]
22 |
23 |
24 | ### Specifications
25 |
26 | - Version of MPC Video Renderer:
27 | - Player version:
28 | - Windows version:
29 | - Name of the graphics adapter:
30 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Build VideoRenderer
2 |
3 | on:
4 | push:
5 | paths-ignore:
6 | - .github/workflows/main.yml
7 | - '**.txt'
8 | - '**.md'
9 | - '**.cmd'
10 | - '**.vcxproj.filters'
11 | pull_request:
12 | paths-ignore:
13 | - .github/workflows/main.yml
14 | - '**.txt'
15 | - '**.md'
16 | - '**.cmd'
17 | - '**.vcxproj.filters'
18 |
19 | jobs:
20 | build:
21 | runs-on: windows-2019
22 |
23 | steps:
24 | - name: Checkout repository
25 | uses: actions/checkout@v4
26 | with:
27 | fetch-depth: 0
28 | submodules: recursive
29 |
30 | - name: Select Windows SDK 10.0.22621.0
31 | run: |
32 | (Get-Content .\\platform.props) | ForEach-Object { $_ -replace ">10.0<", ">10.0.22621.0<" } | Set-Content .\\platform.props
33 | shell: pwsh
34 |
35 | - name: Build VideoRenderer
36 | run: |
37 | .\\build_mpcvr.cmd NoWait
38 | shell: pwsh
39 |
40 | - name: Upload build artifacts
41 | uses: actions/upload-artifact@v4
42 | with:
43 | name: "MPC Video Renderer"
44 | path: _bin/MpcVideoRenderer*.zip
45 | compression-level: 0
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.user
2 | *.aps
3 | *.bak
4 | /.vs
5 | /_bin
6 | /revision.h
7 | /signinfo.txt
8 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "external/BaseClasses"]
2 | path = external/BaseClasses
3 | url = https://github.com/v0lt/BaseClasses.git
4 | [submodule "external/minhook"]
5 | path = external/minhook
6 | url = https://github.com/TsudaKageyu/minhook.git
7 |
--------------------------------------------------------------------------------
/Include/FilterInterfaces.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2017-2024 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | interface __declspec(uuid("3F56FEBC-633C-4C76-8455-0787FC62C8F8")) IExFilterInfo : public IUnknown
24 | {
25 | // The memory for strings and binary data is allocated by the callee
26 | // by using LocalAlloc. It is the caller's responsibility to release the
27 | // memory by calling LocalFree.
28 | STDMETHOD(GetPropertyInt )(LPCSTR field, int *value) PURE;
29 | STDMETHOD(GetPropertyString)(LPCSTR field, LPWSTR *value, unsigned *chars) PURE;
30 | STDMETHOD(GetPropertyBin )(LPCSTR field, LPVOID *value, unsigned *size ) PURE;
31 | };
32 | // return values:
33 | // E_NOTIMPL - method not implemented, any parameters will be ignored.
34 | // E_POINTER - invalid pointer
35 | // E_INVALIDARG - wrong name or type of field
36 | // E_ABORT - field is correct, but the value is undefined
37 | // S_OK - operation successful
38 | //
39 | // available info fields:
40 | // name type filter valid values
41 | // VIDEO_PROFILE int MatroskaSplitter
42 | // VIDEO_PIXEL_FORMAT int MatroskaSplitter
43 | // VIDEO_INTERLACED int MatroskaSplitter,MP4Splitter,RawVideoSplitter 0-progressive, 1-tff, 2-bff
44 | // VIDEO_FLAG_ONLY_DTS int MatroskaSplitter,MP4Splitter 0-no, 1-yes
45 | // VIDEO_DELAY int MP4Splitter
46 | // PALETTE bin MP4Splitter
47 | // VIDEO_COLOR_SPACE bin MatroskaSplitter
48 | // HDR_MASTERING_METADATA bin MatroskaSplitter
49 | // HDR_CONTENT_LIGHT_LEVEL bin MatroskaSplitter
50 |
51 | interface __declspec(uuid("37CBDF10-D65E-4E5A-8F37-40E0C8EA1695")) IExFilterConfig : public IUnknown
52 | {
53 | // The memory for strings and binary data is allocated by the callee
54 | // by using LocalAlloc. It is the caller's responsibility to release the
55 | // memory by calling LocalFree.
56 | STDMETHOD(Flt_GetBool )(LPCSTR field, bool *value) PURE;
57 | STDMETHOD(Flt_GetInt )(LPCSTR field, int *value) PURE;
58 | STDMETHOD(Flt_GetInt64 )(LPCSTR field, __int64 *value) PURE;
59 | STDMETHOD(Flt_GetDouble)(LPCSTR field, double *value) PURE;
60 | STDMETHOD(Flt_GetString)(LPCSTR field, LPWSTR *value, unsigned *chars) PURE;
61 | STDMETHOD(Flt_GetBin )(LPCSTR field, LPVOID *value, unsigned *size ) PURE;
62 |
63 | STDMETHOD(Flt_SetBool )(LPCSTR field, bool value) PURE;
64 | STDMETHOD(Flt_SetInt )(LPCSTR field, int value) PURE;
65 | STDMETHOD(Flt_SetInt64 )(LPCSTR field, __int64 value) PURE;
66 | STDMETHOD(Flt_SetDouble)(LPCSTR field, double value) PURE;
67 | STDMETHOD(Flt_SetString)(LPCSTR field, LPWSTR value, int chars) PURE;
68 | STDMETHOD(Flt_SetBin )(LPCSTR field, LPVOID value, int size ) PURE;
69 | };
70 | // available settings:
71 | // name type filter mode valid values
72 | // stereodownmix bool MpaDecFilter set true/false
73 | // queueDuration int BaseSplitter set/get 100...15000 milliseconds
74 | // networkTimeout int BaseSplitter set/get 2000...20000 milliseconds (reserved)
75 | // version int64 MpcVideoRenderer get 0.3.3.886 or newer
76 | // statsEnable bool MpcVideoRenderer set/get true/false
77 | // cmd_redraw bool MpcVideoRenderer set true
78 | // playbackState int MpcVideoRenderer get 0-State_Stopped, 1-State_Paused, 2-State_Running
79 | // rotation int MpcVideoRenderer get 0, 90, 180, 270 (reserved)
80 |
--------------------------------------------------------------------------------
/Include/FilterInterfacesImpl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2017-2024 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | #include "FilterInterfaces.h"
24 |
25 | class CExFilterInfoImpl : public IExFilterInfo
26 | {
27 | STDMETHODIMP GetPropertyInt (LPCSTR field, int *value) { return E_NOTIMPL; };
28 | STDMETHODIMP GetPropertyString(LPCSTR field, LPWSTR *value, unsigned *chars) { return E_NOTIMPL; };
29 | STDMETHODIMP GetPropertyBin (LPCSTR field, LPVOID *value, unsigned *size ) { return E_NOTIMPL; };
30 | };
31 |
32 | class CExFilterConfigImpl : public IExFilterConfig
33 | {
34 | STDMETHODIMP Flt_GetBool (LPCSTR field, bool *value) { return E_NOTIMPL; };
35 | STDMETHODIMP Flt_GetInt (LPCSTR field, int *value) { return E_NOTIMPL; };
36 | STDMETHODIMP Flt_GetInt64 (LPCSTR field, __int64 *value) { return E_NOTIMPL; };
37 | STDMETHODIMP Flt_GetDouble(LPCSTR field, double *value) { return E_NOTIMPL; };
38 | STDMETHODIMP Flt_GetString(LPCSTR field, LPWSTR *value, unsigned *chars) { return E_NOTIMPL; };
39 | STDMETHODIMP Flt_GetBin (LPCSTR field, LPVOID *value, unsigned *size ) { return E_NOTIMPL; };
40 |
41 | STDMETHODIMP Flt_SetBool (LPCSTR field, bool value) { return E_NOTIMPL; };
42 | STDMETHODIMP Flt_SetInt (LPCSTR field, int value) { return E_NOTIMPL; };
43 | STDMETHODIMP Flt_SetInt64 (LPCSTR field, __int64 value) { return E_NOTIMPL; };
44 | STDMETHODIMP Flt_SetDouble(LPCSTR field, double value) { return E_NOTIMPL; };
45 | STDMETHODIMP Flt_SetString(LPCSTR field, LPWSTR value, int chars) { return E_NOTIMPL; };
46 | STDMETHODIMP Flt_SetBin (LPCSTR field, LPVOID value, int size ) { return E_NOTIMPL; };
47 | };
48 |
--------------------------------------------------------------------------------
/Include/ID3DFullscreenControl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2021 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | // Set and query D3DFullscreen mode.
24 | interface __declspec(uuid("8EA1E899-B77D-4777-9F0E-66421BEA50F8"))
25 | ID3DFullscreenControl :
26 | public IUnknown {
27 | STDMETHOD(SetD3DFullscreen)(bool fEnabled) PURE;
28 | STDMETHOD(GetD3DFullscreen)(bool * pfEnabled) PURE;
29 | };
30 |
--------------------------------------------------------------------------------
/Include/ID3DVideoMemoryConfiguration.h:
--------------------------------------------------------------------------------
1 | // -----------------------------------------------------------------
2 | // ID3DVideoMemoryConfiguration interface and data structure definitions
3 | // -----------------------------------------------------------------
4 | #pragma once
5 |
6 | // -----------------------------------------------------------------
7 | // Control D3D11 Hardware Decoding between decoder and renderer
8 | // -----------------------------------------------------------------
9 | // A video renderer can implement this interface on its input pin
10 | // to signal to a decoder that its capable of accepting D3D11 texture
11 | // samples directly, without copying to system memory.
12 | //
13 | // The decoder will create the D3D11 device and a mutex to protect it,
14 | // and share it with the renderer in this interface.
15 | //
16 | // To facilitate dynamic switching of the adapter used for decoding, the
17 | // renderer should disconnect the decoder and re-connect it. At that
18 | // point the decoder should query GetD3D11AdapterIndex() again and
19 | // create a new decoder on the new device, as appropriate.
20 | interface __declspec(uuid("2BB66002-46B7-4F13-9036-7053328742BE")) ID3D11DecoderConfiguration : public IUnknown
21 | {
22 | // Set the surface format the decoder is going to send.
23 | // If the renderer is not ready to accept this format, an error will be returned.
24 | virtual HRESULT STDMETHODCALLTYPE ActivateD3D11Decoding(ID3D11Device *pDevice, ID3D11DeviceContext *pContext, HANDLE hMutex, UINT nFlags) = 0;
25 |
26 | // Get the currently preferred D3D11 adapter index (to be used with IDXGIFactory1::EnumAdapters1)
27 | virtual UINT STDMETHODCALLTYPE GetD3D11AdapterIndex() = 0;
28 | };
29 |
30 | // -----------------------------------------------------------------
31 | // Media Sample to hold a D3D11 texture
32 | // -----------------------------------------------------------------
33 | // D3D11 textures used for decoding are typically array-textures,
34 | // a single ID3D11Texture2D object containing an array of textures
35 | // individually addressable by the ArraySlice index.
36 | //
37 | // The texture lifetime is bound to the media samples lifetime. The
38 | // media sample can only be released when the texture is no longer in
39 | // use, otherwise the texture will be re-used by the decoder.
40 | //
41 | // The texture is AddRef'ed when retrieved through this interface,
42 | // and should be Released when no longer needed.
43 | interface __declspec(uuid("BC8753F5-0AC8-4806-8E5F-A12B2AFE153E")) IMediaSampleD3D11 : public IUnknown
44 | {
45 | // Get the D3D11 texture for the specified view.
46 | // 2D images with only one view always use view 0. For 3D, view 0 specifies the base view, view 1 the extension view.
47 | virtual HRESULT STDMETHODCALLTYPE GetD3D11Texture(int nView, ID3D11Texture2D **ppTexture, UINT *pArraySlice) = 0;
48 | };
49 |
--------------------------------------------------------------------------------
/Include/ISubRender.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2003-2006 Gabest
3 | * (C) 2006-2016 see Authors.txt
4 | *
5 | * This file is part of MPC-BE.
6 | *
7 | * MPC-BE is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation; either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MPC-BE is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | *
20 | */
21 |
22 | #pragma once
23 |
24 | #include
25 | #include
26 |
27 | interface IDirect3DDevice9;
28 |
29 | DECLARE_INTERFACE_IID_(ISubRenderCallback, IUnknown, "CD6D2AA5-20D3-4ebe-A8A9-34D3B00CC253")
30 | {
31 | // NULL means release current device, textures and other resources
32 | STDMETHOD(SetDevice)(IDirect3DDevice9* dev) PURE;
33 |
34 | // destination video rectangle, will be inside (0, 0)-(width, height)
35 | // width,height is the size of the entire output window
36 | STDMETHOD(Render)(REFERENCE_TIME rtStart,
37 | int left, int top, int right, int bottom,
38 | int width, int height) PURE;
39 | };
40 |
41 | DECLARE_INTERFACE_IID_(ISubRenderCallback2, ISubRenderCallback, "E602585E-C05A-4828-AC69-AF92997F2E0C")
42 | {
43 | STDMETHOD(RenderEx)(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop,
44 | REFERENCE_TIME avgTimePerFrame,
45 | int left, int top, int right, int bottom,
46 | int width, int height) PURE;
47 | };
48 |
49 | DECLARE_INTERFACE_IID_(ISubRenderCallback3, ISubRenderCallback2, "BAC4273A-3EAD-47F5-9710-8488E52AC618")
50 | {
51 | STDMETHOD(RenderEx2)(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop,
52 | REFERENCE_TIME avgTimePerFrame, RECT croppedVideoRect,
53 | RECT originalVideoRect, RECT viewportRect,
54 | const double videoStretchFactor = 1.0) PURE;
55 | };
56 |
57 | DECLARE_INTERFACE_IID_(ISubRenderCallback4, ISubRenderCallback3, "C89CF1D4-29C5-4A96-8AAC-528EC6F7AF1E")
58 | {
59 | STDMETHOD(RenderEx3)(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop,
60 | REFERENCE_TIME avgTimePerFrame, RECT croppedVideoRect,
61 | RECT originalVideoRect, RECT viewportRect,
62 | const double videoStretchFactor = 1.0,
63 | int xOffsetInPixels = 0, DWORD flags = 0) PURE;
64 | };
65 |
66 | DECLARE_INTERFACE_IID_(ISubRender, IUnknown, "9CC7F9F7-3ED1-493c-AF65-527EA1D9947F")
67 | {
68 | STDMETHOD(SetCallback)(ISubRenderCallback* cb) PURE;
69 | };
70 |
--------------------------------------------------------------------------------
/Include/ISubRender11.h:
--------------------------------------------------------------------------------
1 | // EXPERIMENTAL!
2 |
3 | /*
4 | * (C) 2022 see Authors.txt
5 | *
6 | * This file is part of MPC-BE.
7 | *
8 | * MPC-BE is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation; either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * MPC-BE is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with this program. If not, see .
20 | *
21 | */
22 |
23 | #pragma once
24 |
25 | #include
26 | #include
27 |
28 | interface ID3D11DeviceContext1;
29 |
30 | DECLARE_INTERFACE_IID_(ISubRender11Callback, IUnknown, "1B430F17-4CB2-4C6B-A850-1847F9677C75")
31 | {
32 | // NULL means release current device, textures and other resources
33 | STDMETHOD(SetDevice11)(ID3D11Device* dev) PURE;
34 |
35 | // destination video rectangle, will be inside (0, 0)-(width, height)
36 | // width,height is the size of the entire output window
37 | STDMETHOD(Render11)(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop,
38 | REFERENCE_TIME avgTimePerFrame, RECT croppedVideoRect,
39 | RECT originalVideoRect, RECT viewportRect,
40 | const double videoStretchFactor = 1.0,
41 | int xOffsetInPixels = 0, DWORD flags = 0) PURE;
42 | };
43 |
44 | DECLARE_INTERFACE_IID_(ISubRender11, IUnknown, "524FA4AC-35CF-402B-9015-300FBC432563")
45 | {
46 | STDMETHOD(SetCallback11)(ISubRender11Callback* cb) PURE;
47 | };
48 |
--------------------------------------------------------------------------------
/Include/Version.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../revision.h"
4 |
5 | #ifndef REV_DATE
6 | #define REV_DATE 0
7 | #endif
8 |
9 | #ifndef REV_HASH
10 | #define REV_HASH 0
11 | #endif
12 |
13 | #ifndef REV_NUM
14 | #define REV_NUM 0
15 | #endif
16 |
17 | #ifndef REV_BRANCH
18 | #define REV_BRANCH LOCAL
19 | #endif
20 |
21 | #define DO_MAKE_STR(x) #x
22 | #define MAKE_STR(x) DO_MAKE_STR(x)
23 |
24 | #define VER_RELEASE 0
25 |
26 | #define VER_MAJOR 0
27 | #define VER_MINOR 9
28 | #define VER_BUILD 8
29 |
30 | #define VERSION_NUM VER_MAJOR,VER_MINOR,VER_BUILD,REV_NUM
31 | #define VERSION_STR MAKE_STR(VER_MAJOR) "." MAKE_STR(VER_MINOR) "." MAKE_STR(VER_BUILD) "." MAKE_STR(REV_NUM)
32 |
33 | #define BRANCH_STR MAKE_STR(REV_BRANCH)
34 |
--------------------------------------------------------------------------------
/MpcVideoRenderer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.8.34525.116
5 | MinimumVisualStudioVersion = 15.0.27130.2036
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MpcVideoRenderer", "Source\MpcVideoRenderer.vcxproj", "{C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F} = {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}
9 | EndProjectSection
10 | EndProject
11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Include", "Include", "{C7CAE27C-03BC-45F2-BF8E-DEE05DBF37B8}"
12 | ProjectSection(SolutionItems) = preProject
13 | Include\FilterInterfaces.h = Include\FilterInterfaces.h
14 | Include\FilterInterfacesImpl.h = Include\FilterInterfacesImpl.h
15 | Include\ID3DFullscreenControl.h = Include\ID3DFullscreenControl.h
16 | Include\ID3DVideoMemoryConfiguration.h = Include\ID3DVideoMemoryConfiguration.h
17 | Include\IMediaSideData.h = Include\IMediaSideData.h
18 | Include\ISubRender.h = Include\ISubRender.h
19 | Include\ISubRender11.h = Include\ISubRender11.h
20 | Include\SubRenderIntf.h = Include\SubRenderIntf.h
21 | Include\Version.h = Include\Version.h
22 | EndProjectSection
23 | EndProject
24 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shaders", "Shaders\Shaders.vcxproj", "{3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}"
25 | EndProject
26 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "external\BaseClasses.vcxproj", "{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}"
27 | EndProject
28 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minhook", "external\minhook.vcxproj", "{303B855A-137D-45E9-AF6D-B7241C6E66D6}"
29 | EndProject
30 | Global
31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
32 | Debug|x64 = Debug|x64
33 | Debug|x86 = Debug|x86
34 | Release|x64 = Release|x64
35 | Release|x86 = Release|x86
36 | EndGlobalSection
37 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
38 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Debug|x64.ActiveCfg = Debug|x64
39 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Debug|x64.Build.0 = Debug|x64
40 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Debug|x86.ActiveCfg = Debug|Win32
41 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Debug|x86.Build.0 = Debug|Win32
42 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Release|x64.ActiveCfg = Release|x64
43 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Release|x64.Build.0 = Release|x64
44 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Release|x86.ActiveCfg = Release|Win32
45 | {C9CEECB2-947C-4902-BEF9-B98DCAF14B1C}.Release|x86.Build.0 = Release|Win32
46 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Debug|x64.ActiveCfg = Debug|x64
47 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Debug|x64.Build.0 = Debug|x64
48 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Debug|x86.ActiveCfg = Debug|Win32
49 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Debug|x86.Build.0 = Debug|Win32
50 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Release|x64.ActiveCfg = Release|x64
51 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Release|x64.Build.0 = Release|x64
52 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Release|x86.ActiveCfg = Release|Win32
53 | {3D9A1837-4ECC-45CA-9260-F57AD36C6B5F}.Release|x86.Build.0 = Release|Win32
54 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.ActiveCfg = Debug|x64
55 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.Build.0 = Debug|x64
56 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x86.ActiveCfg = Debug|Win32
57 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x86.Build.0 = Debug|Win32
58 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.ActiveCfg = Release|x64
59 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.Build.0 = Release|x64
60 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x86.ActiveCfg = Release|Win32
61 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x86.Build.0 = Release|Win32
62 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Debug|x64.ActiveCfg = Debug|x64
63 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Debug|x64.Build.0 = Debug|x64
64 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Debug|x86.ActiveCfg = Debug|Win32
65 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Debug|x86.Build.0 = Debug|Win32
66 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Release|x64.ActiveCfg = Release|x64
67 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Release|x64.Build.0 = Release|x64
68 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Release|x86.ActiveCfg = Release|Win32
69 | {303B855A-137D-45E9-AF6D-B7241C6E66D6}.Release|x86.Build.0 = Release|Win32
70 | EndGlobalSection
71 | GlobalSection(SolutionProperties) = preSolution
72 | HideSolutionNode = FALSE
73 | EndGlobalSection
74 | GlobalSection(ExtensibilityGlobals) = postSolution
75 | SolutionGuid = {5D7781ED-53B1-4197-9C68-D2EDD94EC59B}
76 | EndGlobalSection
77 | EndGlobal
78 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # MPC Video Renderer
2 |
3 | MPC Video Renderer is a free and open-source video renderer for DirectShow. The renderer can potentially work with any DirectShow player, but full support is available only in the MPC-BE. Recommended MPC-BE 1.8.2.136 or newer.
4 |
5 | ## Key features
6 |
7 | * Can work with DXVA2 and Direct3D 11 hardware decoder.
8 | * DVXA2 and Direct3D11 Video Processor with hardware de-interlacing for NV12, YUY2, P010 formats.
9 | * Shader video processor for various YUV, RGB and grayscale formats.
10 | * Various frame resizing algorithms, including Super Resolution.
11 | * Subtitle and OSD display.
12 | * Rotation and flip of the video frame.
13 | * Dithering when the final color depth is reduced from 10/16 bits to 8 bits.
14 | * HDR video support (HDR10, HLG and partially Dolby Vision).
15 | * Automatic HDR to SDR conversion.
16 | * Transferring HDR10 data to the display.
17 |
18 | ## Minimum system requirements
19 |
20 | * An SSE2-capable CPU
21 | * Windows 7¹ or newer
22 | * DirectX 9.0c video card
23 |
24 | ¹For Windows 7, you must have D3DCompiler_47.dll file. It can be installed via update KB4019990.
25 |
26 | ## Recommended system requirements
27 |
28 | * An SSE2-capable CPU
29 | * Windows 10 or newer
30 | * DirectX 10/11 video card
31 |
32 | ## License
33 |
34 | MPC Video Renderer's code is licensed under [GPL v3].
35 |
36 | ## Links
37 |
38 | [Nightly builds](https://github.com/Aleksoid1978/VideoRenderer/wiki/Nightly-builds)
39 |
40 | [Topic in MPC-BE forum (Russian)](https://mpc-be.org/forum/index.php?topic=381)
41 |
42 | [MPC-BE](https://github.com/Aleksoid1978/MPC-BE)
43 |
44 | ## Donate
45 |
46 |
47 |
--------------------------------------------------------------------------------
/Shaders/convert/colorspace_gamut_conversion.hlsl:
--------------------------------------------------------------------------------
1 | // using code from zimg - https://github.com/sekrit-twc/zimg
2 |
3 | #pragma warning(disable: 4122) // disable warning X4122: sum of ... cannot be represented accurately in double precision.
4 |
5 | static const float REC_709_PRIMARIES[3][2] = { { 0.640, 0.330 }, { 0.300, 0.600 }, { 0.150, 0.060 } };
6 | static const float REC_2020_PRIMARIES[3][2] = { { 0.708, 0.292 }, { 0.170, 0.797 }, { 0.131, 0.046 } };
7 |
8 | static const float ILLUMINANT_D65[2] = { 0.3127, 0.3290 };
9 |
10 | const float det2(const float a00, const float a01, const float a10, const float a11)
11 | {
12 | return a00 * a11 - a01 * a10;
13 | }
14 |
15 | const float determinant(const float3x3 m)
16 | {
17 | float det = 0;
18 |
19 | det += m[0][0] * det2(m[1][1], m[1][2], m[2][1], m[2][2]);
20 | det -= m[0][1] * det2(m[1][0], m[1][2], m[2][0], m[2][2]);
21 | det += m[0][2] * det2(m[1][0], m[1][1], m[2][0], m[2][1]);
22 |
23 | return det;
24 | }
25 |
26 | const float3x3 inverse(const float3x3 m)
27 | {
28 | float3x3 ret;
29 | const float det = determinant(m);
30 |
31 | ret[0][0] = det2(m[1][1], m[1][2], m[2][1], m[2][2]) / det;
32 | ret[0][1] = det2(m[0][2], m[0][1], m[2][2], m[2][1]) / det;
33 | ret[0][2] = det2(m[0][1], m[0][2], m[1][1], m[1][2]) / det;
34 | ret[1][0] = det2(m[1][2], m[1][0], m[2][2], m[2][0]) / det;
35 | ret[1][1] = det2(m[0][0], m[0][2], m[2][0], m[2][2]) / det;
36 | ret[1][2] = det2(m[0][2], m[0][0], m[1][2], m[1][0]) / det;
37 | ret[2][0] = det2(m[1][0], m[1][1], m[2][0], m[2][1]) / det;
38 | ret[2][1] = det2(m[0][1], m[0][0], m[2][1], m[2][0]) / det;
39 | ret[2][2] = det2(m[0][0], m[0][1], m[1][0], m[1][1]) / det;
40 |
41 | return ret;
42 | }
43 |
44 | const float3 xy_to_xyz(const float x, const float y)
45 | {
46 | float3 ret;
47 |
48 | ret[0] = x / y;
49 | ret[1] = 1.0;
50 | ret[2] = (1.0 - x - y) / y;
51 |
52 | return ret;
53 | }
54 |
55 | const float3 get_d65_xyz()
56 | {
57 | return xy_to_xyz(ILLUMINANT_D65[0], ILLUMINANT_D65[1]);
58 | }
59 |
60 | const float3x3 get_primaries_xyz(const float primaries_xy[3][2])
61 | {
62 | // Columns: R G B
63 | // Rows: X Y Z
64 | float3x3 ret;
65 |
66 | ret[0] = xy_to_xyz(primaries_xy[0][0], primaries_xy[0][1]);
67 | ret[1] = xy_to_xyz(primaries_xy[1][0], primaries_xy[1][1]);
68 | ret[2] = xy_to_xyz(primaries_xy[2][0], primaries_xy[2][1]);
69 |
70 | return transpose(ret);
71 | }
72 |
73 | const float3x3 gamut_rgb_to_xyz_matrix(const float primaries_xy[3][2])
74 | {
75 | const float3x3 xyz_matrix = get_primaries_xyz(primaries_xy);
76 | const float3 white_xyz = get_d65_xyz();
77 |
78 | const float3 s = mul(inverse(xyz_matrix), white_xyz);
79 | const float3x3 m = { xyz_matrix[0] * s, xyz_matrix[1] * s, xyz_matrix[2] * s };
80 |
81 | return m;
82 | }
83 |
84 | static const float3x3 gamut_xyz_color_matrix_2020 = gamut_rgb_to_xyz_matrix(REC_2020_PRIMARIES);
85 | static const float3x3 gamut_xyz_color_matrix_709 = gamut_rgb_to_xyz_matrix(REC_709_PRIMARIES);
86 | static const float3x3 convert_matrix_2020_to_709 = mul(inverse(gamut_xyz_color_matrix_709), gamut_xyz_color_matrix_2020);
87 |
88 | float3 Colorspace_Gamut_Conversion_2020_to_709(const float3 rgb)
89 | {
90 | return mul(convert_matrix_2020_to_709, rgb);
91 | }
92 |
--------------------------------------------------------------------------------
/Shaders/convert/conv_matrix.hlsl:
--------------------------------------------------------------------------------
1 | static float4x4 rgb_ycbcr709 = {
2 | 0.2126, 0.7152, 0.0722, 0.0,
3 | -0.114572, -0.385428, 0.5, 0.0,
4 | 0.5, -0.454153, -0.045847, 0.0,
5 | 0.0, 0.0, 0.0, 0.0
6 | };
7 |
8 | static float4x4 ycbcr2020nc_rgb = {
9 | 1.0, 0.0, 1.4746, 0.0,
10 | 1.0, -0.164553, -0.571353, 0.0,
11 | 1.0, 1.8814, 0.0, 0.0,
12 | 0.0, 0.0, 0.0, 0.0
13 | };
14 |
15 | static float4x4 ycgco_rgb = {
16 | 1.0, -1.0, 1.0, 0.0,
17 | 1.0, 1.0, 0.0, 0.0,
18 | 1.0, -1.0, -1.0, 0.0,
19 | 0.0, 0.0, 0.0, 0.0
20 | };
21 |
--------------------------------------------------------------------------------
/Shaders/convert/hdr_tone_mapping.hlsl:
--------------------------------------------------------------------------------
1 | inline float3 hable(float3 x)
2 | {
3 | const float A = 0.15, B = 0.50, C = 0.10, D = 0.20, E = 0.02, F = 0.30;
4 |
5 | return ((x * (A * x + (C * B)) + (D * E)) / (x * (A * x + B) + (D * F))) - E / F;
6 | }
7 |
8 | float3 ToneMappingHable(const float3 rgb)
9 | {
10 | static const float3 HABLE_DIV = hable(4.8);
11 |
12 | return hable(rgb) / HABLE_DIV;
13 | }
14 |
--------------------------------------------------------------------------------
/Shaders/convert/hlg.hlsl:
--------------------------------------------------------------------------------
1 | inline float3 inverse_HLG(float3 rgb)
2 | {
3 | const float B67_a = 0.17883277;
4 | const float B67_b = 0.28466892;
5 | const float B67_c = 0.55991073;
6 | const float B67_inv_r2 = 4.0;
7 | rgb = (rgb <= 0.5)
8 | ? rgb * rgb * B67_inv_r2
9 | : exp((rgb - B67_c) / B67_a) + B67_b;
10 | return rgb;
11 | }
12 |
13 | inline float3 HLGtoLinear(float3 rgb)
14 | {
15 | rgb = inverse_HLG(rgb);
16 | float3 ootf_2020 = float3(0.2627, 0.6780, 0.0593);
17 | float ootf_ys = 2000.0f * dot(ootf_2020, rgb);
18 | rgb *= pow(ootf_ys, 0.2f);
19 | return rgb;
20 | }
21 |
--------------------------------------------------------------------------------
/Shaders/convert/st2084.hlsl:
--------------------------------------------------------------------------------
1 | static const float ST2084_m1 = 2610.0f / (4096.0f * 4.0f);
2 | static const float ST2084_m2 = (2523.0f / 4096.0f) * 128.0f;
3 | static const float ST2084_c1 = 3424.0f / 4096.0f;
4 | static const float ST2084_c2 = (2413.0f / 4096.0f) * 32.0f;
5 | static const float ST2084_c3 = (2392.0f / 4096.0f) * 32.0f;
6 |
7 | #pragma warning(disable: 3571)
8 |
9 | inline float4 ST2084ToLinear(float4 rgb, float factor)
10 | {
11 | rgb = pow(rgb, 1.0 / ST2084_m2);
12 | rgb = max(rgb - ST2084_c1, 0.0) / (ST2084_c2 - ST2084_c3 * rgb);
13 | rgb = pow(rgb, 1.0 / ST2084_m1);
14 | rgb *= factor;
15 | return rgb;
16 | }
17 |
18 | inline float4 LinearToST2084(float4 rgb, float divider)
19 | {
20 | rgb /= divider;
21 | rgb = pow(rgb, ST2084_m1);
22 | rgb = (ST2084_c1 + ST2084_c2 * rgb) / (1.0f + ST2084_c3 * rgb);
23 | rgb = pow(rgb, ST2084_m2);
24 | return rgb;
25 | }
26 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_TEST.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D tex : register(t0);
2 | SamplerState samp : register(s0);
3 |
4 | struct PS_INPUT
5 | {
6 | float4 Pos : SV_POSITION;
7 | float2 Tex : TEXCOORD;
8 | };
9 |
10 | float4 main(PS_INPUT input) : SV_Target
11 | {
12 | float4 pixel = tex.Sample(samp, input.Tex);
13 |
14 | // write test code here
15 |
16 | return pixel;
17 | }
18 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_convert_biplanar.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D texY : register(t0);
2 | Texture2D texUV : register(t1);
3 | SamplerState samp : register(s0);
4 | SamplerState sampL : register(s1);
5 |
6 | cbuffer PS_COLOR_TRANSFORM : register(b0)
7 | {
8 | float3 cm_r;
9 | float3 cm_g;
10 | float3 cm_b;
11 | float3 cm_c;
12 | // NB: sizeof(float3) == sizeof(float4)
13 | };
14 |
15 | struct PS_INPUT
16 | {
17 | float4 Pos : SV_POSITION;
18 | float2 Tex : TEXCOORD;
19 | };
20 |
21 | float4 main(PS_INPUT input) : SV_Target
22 | {
23 | float colorY = texY.Sample(samp, input.Tex).r;
24 | float2 colorUV = texUV.Sample(sampL, input.Tex).rg;
25 |
26 | float4 color = float4(colorY, colorUV, 0);
27 |
28 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c;
29 |
30 | return color;
31 | }
32 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_convert_bitmap_to_pq.hlsl:
--------------------------------------------------------------------------------
1 | #ifndef SDR_PEAK_LUM
2 | #define SDR_PEAK_LUM 100
3 | #endif
4 |
5 | Texture2D tex : register(t0);
6 | SamplerState samp : register(s0);
7 |
8 | struct PS_INPUT
9 | {
10 | float4 Pos : SV_POSITION;
11 | float2 Tex : TEXCOORD;
12 | };
13 |
14 | #pragma warning(disable: 3571) // fix warning X3571 in pow().
15 |
16 | // https://github.com/thexai/xbmc/blob/master/system/shaders/guishader_common.hlsl
17 | inline float3 transferPQ(float3 x)
18 | {
19 | static const float ST2084_m1 = 2610.0f / (4096.0f * 4.0f);
20 | static const float ST2084_m2 = (2523.0f / 4096.0f) * 128.0f;
21 | static const float ST2084_c1 = 3424.0f / 4096.0f;
22 | static const float ST2084_c2 = (2413.0f / 4096.0f) * 32.0f;
23 | static const float ST2084_c3 = (2392.0f / 4096.0f) * 32.0f;
24 | static const float SDR_peak_lum = SDR_PEAK_LUM;
25 | static const float3x3 matx = {
26 | 0.627402, 0.329292, 0.043306,
27 | 0.069095, 0.919544, 0.011360,
28 | 0.016394, 0.088028, 0.895578
29 | };
30 | // REC.709 to linear
31 | x = pow(x, 1.0f / 0.45f);
32 | // REC.709 to BT.2020
33 | x = mul(matx, x);
34 | // linear to PQ
35 | x = pow(x / SDR_peak_lum, ST2084_m1);
36 | x = (ST2084_c1 + ST2084_c2 * x) / (1.0f + ST2084_c3 * x);
37 | x = pow(x, ST2084_m2);
38 | return x;
39 | }
40 |
41 | float4 main(PS_INPUT input) : SV_Target
42 | {
43 | float4 color = tex.Sample(samp, input.Tex); // original pixel
44 |
45 | return float4(transferPQ(color.rgb), color.a);
46 | }
47 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_convert_color.hlsl:
--------------------------------------------------------------------------------
1 | #ifndef C_YUY2
2 | #define C_YUY2 0
3 | #endif
4 |
5 | Texture2D tex : register(t0);
6 | SamplerState samp : register(s0);
7 |
8 | cbuffer PS_COLOR_TRANSFORM : register(b0)
9 | {
10 | float3 cm_r;
11 | float3 cm_g;
12 | float3 cm_b;
13 | float3 cm_c;
14 | // NB: sizeof(float3) == sizeof(float4)
15 | };
16 | #if C_YUY2
17 | cbuffer PS_TEX_DIMENSIONS : register(b4)
18 | {
19 | float width;
20 | float height;
21 | float dx;
22 | float dy;
23 | };
24 | #endif
25 |
26 | struct PS_INPUT
27 | {
28 | float4 Pos : SV_POSITION;
29 | float2 Tex : TEXCOORD;
30 | };
31 |
32 | float4 main(PS_INPUT input) : SV_Target
33 | {
34 | float4 color = tex.Sample(samp, input.Tex); // original pixel
35 | #if C_YUY2
36 | if (fmod(input.Tex.x*width, 2) < 1.0) {
37 | color = float4(color[0], color[1], color[3], 0);
38 | } else {
39 | #if (C_YUY2 == 1) // nearest neighbor
40 | color = float4(color[2], color[1], color[3], 0);
41 | #elif (C_YUY2 == 2) // linear
42 | float2 chroma0 = color.yw;
43 | float2 chroma1 = tex.Sample(samp, input.Tex + float2(dx, 0)).yw;
44 | float2 chroma = (chroma0 + chroma1) * 0.5;
45 | color = float4(color[2], chroma, 0);
46 | #elif (C_YUY2 == 3) // cubic
47 | float2 chroma0 = tex.Sample(samp, input.Tex + float2(-dx, 0)).yw;
48 | float2 chroma1 = color.yw;
49 | float2 chroma2 = tex.Sample(samp, input.Tex + float2(dx, 0)).yw;
50 | float2 chroma3 = tex.Sample(samp, input.Tex + float2(2*dx, 0)).yw;
51 | float2 chroma = (9 * (chroma1 + chroma2) - (chroma0 + chroma3)) * 0.0625;
52 | color = float4(color[2], chroma, 0);
53 | #endif
54 | }
55 | #endif
56 |
57 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c;
58 |
59 | return color;
60 | }
61 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_convert_hlg_to_pq.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D tex : register(t0);
2 | SamplerState samp : register(s0);
3 |
4 | #include "../convert/hlg.hlsl"
5 | #include "../convert/st2084.hlsl"
6 |
7 | struct PS_INPUT
8 | {
9 | float4 Pos : SV_POSITION;
10 | float2 Tex : TEXCOORD;
11 | };
12 |
13 | float4 main(PS_INPUT input) : SV_Target
14 | {
15 | float4 color = tex.Sample(samp, input.Tex); // original pixel
16 |
17 | color = saturate(color); // use saturate(), because pow() can not take negative values
18 | color.rgb = HLGtoLinear(color.rgb);
19 | color = LinearToST2084(color, 1000.0);
20 |
21 | return color;
22 | }
23 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_convert_planar.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D texY : register(t0);
2 | Texture2D texU : register(t1);
3 | Texture2D texV : register(t2);
4 | SamplerState samp : register(s0);
5 | SamplerState sampL : register(s1);
6 |
7 | cbuffer PS_COLOR_TRANSFORM : register(b0)
8 | {
9 | float3 cm_r;
10 | float3 cm_g;
11 | float3 cm_b;
12 | float3 cm_c;
13 | // NB: sizeof(float3) == sizeof(float4)
14 | };
15 |
16 | struct PS_INPUT
17 | {
18 | float4 Pos : SV_POSITION;
19 | float2 Tex : TEXCOORD;
20 | };
21 |
22 | float4 main(PS_INPUT input) : SV_Target
23 | {
24 | float colorY = texY.Sample(samp, input.Tex).r;
25 | float colorU = texU.Sample(sampL, input.Tex).r;
26 | float colorV = texV.Sample(sampL, input.Tex).r;
27 |
28 | float4 color = float4(colorY, colorU, colorV, 0);
29 |
30 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c;
31 |
32 | return color;
33 | }
34 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_convert_planar_yv.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D texY : register(t0);
2 | Texture2D texV : register(t1);
3 | Texture2D texU : register(t2);
4 | SamplerState samp : register(s0);
5 | SamplerState sampL : register(s1);
6 |
7 | cbuffer PS_COLOR_TRANSFORM : register(b0)
8 | {
9 | float3 cm_r;
10 | float3 cm_g;
11 | float3 cm_b;
12 | float3 cm_c;
13 | // NB: sizeof(float3) == sizeof(float4)
14 | };
15 |
16 | struct PS_INPUT
17 | {
18 | float4 Pos : SV_POSITION;
19 | float2 Tex : TEXCOORD;
20 | };
21 |
22 | float4 main(PS_INPUT input) : SV_Target
23 | {
24 | float colorY = texY.Sample(samp, input.Tex).r;
25 | float colorU = texU.Sample(sampL, input.Tex).r;
26 | float colorV = texV.Sample(sampL, input.Tex).r;
27 |
28 | float4 color = float4(colorY, colorU, colorV, 0);
29 |
30 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c;
31 |
32 | return color;
33 | }
34 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_convert_pq_to_sdr.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D tex : register(t0);
2 | SamplerState samp : register(s0);
3 |
4 | cbuffer PS_PARAMETERS : register(b0)
5 | {
6 | float LuminanceScale;
7 | float param2;
8 | };
9 |
10 | #include "../convert/conv_matrix.hlsl"
11 | #include "../convert/st2084.hlsl"
12 | #include "../convert/hdr_tone_mapping.hlsl"
13 | #include "../convert/colorspace_gamut_conversion.hlsl"
14 |
15 | struct PS_INPUT
16 | {
17 | float4 Pos : SV_POSITION;
18 | float2 Tex : TEXCOORD;
19 | };
20 |
21 | float4 main(PS_INPUT input) : SV_Target
22 | {
23 | float4 color = tex.Sample(samp, input.Tex); // original pixel
24 |
25 | // PQ to Linear
26 | color = saturate(color);
27 | color = ST2084ToLinear(color, LuminanceScale);
28 |
29 | color.rgb = ToneMappingHable(color.rgb);
30 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
31 |
32 | // Linear to sRGB
33 | color = saturate(color);
34 | color = pow(color, 1.0 / 2.2);
35 |
36 | return color;
37 | }
38 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_convolution.hlsl:
--------------------------------------------------------------------------------
1 | #ifndef AXIS
2 | #define AXIS 0
3 | #endif
4 |
5 | #include "../resize/convolution_filters.hlsl"
6 |
7 | Texture2D tex : register(t0);
8 | SamplerState samp : register(s0);
9 |
10 | cbuffer PS_CONSTANTS : register(b0)
11 | {
12 | float2 wh;
13 | float2 dxdy;
14 | float2 scale;
15 | };
16 |
17 | struct PS_INPUT
18 | {
19 | float4 Pos : SV_POSITION;
20 | float2 Tex : TEXCOORD;
21 | };
22 |
23 | static const float support = filter_support * scale[AXIS];
24 | static const float ss = 1.0 / scale[AXIS];
25 |
26 | #pragma warning(disable: 3595) // disable warning X3595: gradient instruction used in a loop with varying iteration; partial derivatives may have undefined value
27 |
28 | float4 main(PS_INPUT input) : SV_Target
29 | {
30 | float pos = input.Tex[AXIS] * wh[AXIS] + 0.5;
31 |
32 | int low = (int)floor(pos - support);
33 | int high = (int)ceil(pos + support);
34 |
35 | float ww = 0.0;
36 | float4 avg = 0;
37 |
38 | [loop] for (int n = low; n < high; n++) {
39 | float w = filter((n - pos + 0.5) * ss);
40 | ww += w;
41 | #if (AXIS == 0)
42 | avg += w * tex.Sample(samp, float2((n + 0.5) * dxdy.x, input.Tex.y));
43 | #else
44 | avg += w * tex.Sample(samp, float2(input.Tex.x, (n + 0.5) * dxdy.y));
45 | #endif
46 | }
47 | avg /= ww;
48 |
49 | return avg;
50 | }
51 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_final_pass.hlsl:
--------------------------------------------------------------------------------
1 |
2 | #ifndef QUANTIZATION
3 | // 255 or 1023 (Maximum quantized integer value)
4 | #define QUANTIZATION 255
5 | #endif
6 |
7 | Texture2D tex : register(t0);
8 | Texture2D texDither : register(t1);
9 | SamplerState samp : register(s0);
10 | SamplerState sampDither : register(s1);
11 |
12 | cbuffer PS_CONSTANTS : register(b0)
13 | {
14 | float2 ditherCoordScale;
15 | };
16 |
17 | struct PS_INPUT
18 | {
19 | float4 Pos : SV_POSITION;
20 | float2 Tex : TEXCOORD;
21 | };
22 |
23 | float4 main(PS_INPUT input) : SV_Target
24 | {
25 | float4 pixel = tex.Sample(samp, input.Tex);
26 |
27 | float4 ditherValue = texDither.Sample(sampDither, input.Tex * ditherCoordScale);
28 | pixel = floor(pixel * QUANTIZATION + ditherValue) / QUANTIZATION;
29 |
30 | return pixel;
31 | };
32 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_fix_bt2020.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D tex : register(t0);
2 | SamplerState samp : register(s0);
3 |
4 | #include "../convert/conv_matrix.hlsl"
5 | #include "../convert/colorspace_gamut_conversion.hlsl"
6 |
7 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);
8 |
9 | struct PS_INPUT
10 | {
11 | float4 Pos : SV_POSITION;
12 | float2 Tex : TEXCOORD;
13 | };
14 |
15 | float4 main(PS_INPUT input) : SV_Target
16 | {
17 | float4 color = tex.Sample(samp, input.Tex);
18 |
19 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in D3D11 VP
20 | color = mul(fix_bt2020_matrix, color);
21 |
22 | // sRGB to Linear
23 | color = saturate(color);
24 | color = pow(color, 2.2);
25 |
26 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
27 |
28 | // Linear to sRGB
29 | color = saturate(color);
30 | color = pow(color, 1.0 / 2.2);
31 |
32 | return color;
33 | }
34 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_fix_ycgco.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D tex : register(t0);
2 | SamplerState samp : register(s0);
3 |
4 | #include "../convert/conv_matrix.hlsl"
5 |
6 | static const float4x4 fix_ycgco_matrix = mul(ycgco_rgb, rgb_ycbcr709);
7 |
8 | struct PS_INPUT
9 | {
10 | float4 Pos : SV_POSITION;
11 | float2 Tex : TEXCOORD;
12 | };
13 |
14 | float4 main(PS_INPUT input) : SV_Target
15 | {
16 | float4 pixel = tex.Sample(samp, input.Tex); // original pixel
17 |
18 | // Fix incorrect (unsupported) conversion from YCgCo to RGB in D3D11 VP
19 | pixel = mul(fix_ycgco_matrix, pixel);
20 |
21 | return pixel;
22 | }
23 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_fixconvert_hlg_to_sdr.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D tex : register(t0);
2 | SamplerState samp : register(s0);
3 |
4 | #include "../convert/conv_matrix.hlsl"
5 | #include "../convert/hlg.hlsl"
6 | #include "../convert/st2084.hlsl"
7 | #include "../convert/hdr_tone_mapping.hlsl"
8 | #include "../convert/colorspace_gamut_conversion.hlsl"
9 |
10 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);
11 |
12 | cbuffer PS_PARAMETERS : register(b0)
13 | {
14 | float LuminanceScale;
15 | float param2;
16 | };
17 |
18 | struct PS_INPUT
19 | {
20 | float4 Pos : SV_POSITION;
21 | float2 Tex : TEXCOORD;
22 | };
23 |
24 | float4 main(PS_INPUT input) : SV_Target
25 | {
26 | float4 color = tex.Sample(samp, input.Tex); // original pixel
27 |
28 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in D3D11 VP
29 | color = mul(fix_bt2020_matrix, color);
30 |
31 | // HLG to PQ
32 | color = saturate(color);
33 | color.rgb = HLGtoLinear(color.rgb);
34 | color = LinearToST2084(color, 1000.0);
35 |
36 | // PQ to Linear
37 | color = saturate(color);
38 | color = ST2084ToLinear(color, LuminanceScale);
39 |
40 | color.rgb = ToneMappingHable(color.rgb);
41 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
42 |
43 | // Linear to sRGB
44 | color = saturate(color);
45 | color = pow(color, 1.0 / 2.2);
46 |
47 | return color;
48 | }
49 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_fixconvert_pq_to_sdr.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D tex : register(t0);
2 | SamplerState samp : register(s0);
3 |
4 | cbuffer PS_PARAMETERS : register(b0)
5 | {
6 | float LuminanceScale;
7 | float param2;
8 | };
9 |
10 | #include "../convert/conv_matrix.hlsl"
11 | #include "../convert/st2084.hlsl"
12 | #include "../convert/hdr_tone_mapping.hlsl"
13 | #include "../convert/colorspace_gamut_conversion.hlsl"
14 |
15 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);
16 |
17 | struct PS_INPUT
18 | {
19 | float4 Pos : SV_POSITION;
20 | float2 Tex : TEXCOORD;
21 | };
22 |
23 | float4 main(PS_INPUT input) : SV_Target
24 | {
25 | float4 color = tex.Sample(samp, input.Tex); // original pixel
26 |
27 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in D3D11 VP
28 | color = mul(fix_bt2020_matrix, color);
29 |
30 | // PQ to Linear
31 | color = saturate(color);
32 | color = ST2084ToLinear(color, LuminanceScale);
33 |
34 | color.rgb = ToneMappingHable(color.rgb);
35 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
36 |
37 | // Linear to sRGB
38 | color = saturate(color);
39 | color = pow(color, 1.0 / 2.2);
40 |
41 | return color;
42 | }
43 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_font.hlsl:
--------------------------------------------------------------------------------
1 | // pixel shader for D3D11Font
2 | Texture2D shaderTexture;
3 | SamplerState SampleType;
4 |
5 | cbuffer PS_COLOR
6 | {
7 | float4 pixelColor;
8 | };
9 |
10 | struct PS_INPUT
11 | {
12 | float4 pos : SV_POSITION;
13 | float2 tex : TEXCOORD;
14 | };
15 |
16 | float4 main(PS_INPUT input) : SV_Target
17 | {
18 | return shaderTexture.Sample(SampleType, input.tex) * pixelColor;
19 | }
20 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_geometry.hlsl:
--------------------------------------------------------------------------------
1 | // pixel shader for D3D11Geometry
2 | struct PS_INPUT
3 | {
4 | float4 position : SV_POSITION;
5 | float4 color : COLOR;
6 | };
7 |
8 | float4 main(PS_INPUT input) : SV_Target
9 | {
10 | return input.color;
11 | }
12 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_halfoverunder_to_interlace.hlsl:
--------------------------------------------------------------------------------
1 | // convert Half OverUnder to Interlace
2 |
3 | Texture2D tex : register(t0);
4 | SamplerState samp : register(s0);
5 |
6 | cbuffer PS_CONSTANTS : register(b0)
7 | {
8 | float height;
9 | float none;
10 | float dtop;
11 | float dbottom;
12 | };
13 |
14 | struct PS_INPUT
15 | {
16 | float4 Pos : SV_POSITION;
17 | float2 Tex : TEXCOORD;
18 | };
19 |
20 | float4 main(PS_INPUT input) : SV_Target
21 | {
22 | float2 pos = input.Tex;
23 |
24 | if (pos.y >= dbottom) {
25 | return float4(0.0, 0.0, 0.0, 1.0);
26 | }
27 |
28 | if (fmod((pos.y - dtop) * height, 2) < 1.0) {
29 | // even
30 | pos.y = (dtop + pos.y) / 2;
31 | } else {
32 | // odd
33 | pos.y = (dbottom + pos.y) / 2;
34 | }
35 |
36 | return tex.Sample(samp, pos);
37 | }
38 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_interpolation_lanczos2.hlsl:
--------------------------------------------------------------------------------
1 | #ifndef AXIS
2 | #define AXIS 0
3 | #endif
4 |
5 | #define PI acos(-1.)
6 |
7 | Texture2D tex : register(t0);
8 | SamplerState samp : register(s0);
9 |
10 | cbuffer PS_CONSTANTS : register(b0)
11 | {
12 | float2 wh;
13 | float2 dxdy;
14 | float2 scale;
15 | };
16 |
17 | struct PS_INPUT
18 | {
19 | float4 Pos : SV_POSITION;
20 | float2 Tex : TEXCOORD;
21 | };
22 |
23 | float4 main(PS_INPUT input) : SV_Target
24 | {
25 | float pos = input.Tex[AXIS] * wh[AXIS] - 0.5;
26 | float t = frac(pos); // calculate the difference between the output pixel and the original surrounding two pixels
27 | pos = pos - t;
28 |
29 | #if (AXIS == 0)
30 | float4 Q1 = tex.Sample(samp, float2((pos + 0.5) * dxdy.x, input.Tex.y)); // nearest original pixel to the left
31 | if (t) {
32 | // original pixels
33 | float4 Q0 = tex.Sample(samp, float2((pos - 0.5) * dxdy.x, input.Tex.y));
34 | float4 Q2 = tex.Sample(samp, float2((pos + 1.5) * dxdy.x, input.Tex.y));
35 | float4 Q3 = tex.Sample(samp, float2((pos + 2.5) * dxdy.x, input.Tex.y));
36 | #elif (AXIS == 1)
37 | float4 Q1 = tex.Sample(samp, float2(input.Tex.x, (pos + 0.5) * dxdy.y));
38 | if (t) {
39 | // original pixels
40 | float4 Q0 = tex.Sample(samp, float2(input.Tex.x, (pos - 0.5) * dxdy.y));
41 | float4 Q2 = tex.Sample(samp, float2(input.Tex.x, (pos + 1.5) * dxdy.y));
42 | float4 Q3 = tex.Sample(samp, float2(input.Tex.x, (pos + 2.5) * dxdy.y));
43 | #else
44 | #error ERROR: incorrect AXIS.
45 | #endif
46 | float4 wset = float3(0., 1., 2.).yxyz + float2(t, -t).xxyy;
47 | float4 w = sin(wset * PI) * sin(wset * PI * .5) / (wset * wset * PI * PI * .5);
48 |
49 | float wc = 1. - dot(1., w); // compensate truncated window factor by bilinear factoring on the two nearest samples
50 | w.y += wc * (1. - t);
51 | w.z += wc * t;
52 |
53 | return w.x * Q0 + w.y * Q1 + w.z * Q2 + w.w * Q3; // interpolation output
54 | }
55 |
56 | return Q1; // case t == 0. is required to return sample Q1, because of a possible division by 0.
57 | }
58 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_interpolation_lanczos3.hlsl:
--------------------------------------------------------------------------------
1 | #ifndef AXIS
2 | #define AXIS 0
3 | #endif
4 |
5 | #define PI acos(-1.)
6 |
7 | Texture2D tex : register(t0);
8 | SamplerState samp : register(s0);
9 |
10 | cbuffer PS_CONSTANTS : register(b0)
11 | {
12 | float2 wh;
13 | float2 dxdy;
14 | float2 scale;
15 | };
16 |
17 | struct PS_INPUT
18 | {
19 | float4 Pos : SV_POSITION;
20 | float2 Tex : TEXCOORD;
21 | };
22 |
23 | float4 main(PS_INPUT input) : SV_Target
24 | {
25 | float pos = input.Tex[AXIS] * wh[AXIS] - 0.5;
26 | float t = frac(pos); // calculate the difference between the output pixel and the original surrounding two pixels
27 | pos = pos - t;
28 |
29 | #if (AXIS == 0)
30 | float4 Q2 = tex.Sample(samp, float2((pos + 0.5) * dxdy.x, input.Tex.y)); // nearest original pixel to the left
31 | if (t) {
32 | // original pixels
33 | float4 Q0 = tex.Sample(samp, float2((pos - 1.5) * dxdy.x, input.Tex.y));
34 | float4 Q1 = tex.Sample(samp, float2((pos - 1.5) * dxdy.x, input.Tex.y));
35 | float4 Q3 = tex.Sample(samp, float2((pos + 1.5) * dxdy.x, input.Tex.y));
36 | float4 Q4 = tex.Sample(samp, float2((pos + 2.5) * dxdy.x, input.Tex.y));
37 | float4 Q5 = tex.Sample(samp, float2((pos + 3.5) * dxdy.x, input.Tex.y));
38 | #elif (AXIS == 1)
39 | float4 Q2 = tex.Sample(samp, float2(input.Tex.x, (pos + 0.5) * dxdy.y));
40 | if (t) {
41 | // original pixels
42 | float4 Q0 = tex.Sample(samp, float2(input.Tex.x, (pos - 1.5) * dxdy.y));
43 | float4 Q1 = tex.Sample(samp, float2(input.Tex.x, (pos - 1.5) * dxdy.y));
44 | float4 Q3 = tex.Sample(samp, float2(input.Tex.x, (pos + 1.5) * dxdy.y));
45 | float4 Q4 = tex.Sample(samp, float2(input.Tex.x, (pos + 2.5) * dxdy.y));
46 | float4 Q5 = tex.Sample(samp, float2(input.Tex.x, (pos + 3.5) * dxdy.y));
47 | #else
48 | #error ERROR: incorrect AXIS.
49 | #endif
50 | float3 wset0 = float3(2., 1., 0.) * PI + t * PI;
51 | float3 wset1 = float3(1., 2., 3.) * PI - t * PI;
52 | float3 wset0s = wset0 * .5;
53 | float3 wset1s = wset1 * .5;
54 | float3 w0 = sin(wset0) * sin(wset0s) / (wset0 * wset0s);
55 | float3 w1 = sin(wset1) * sin(wset1s) / (wset1 * wset1s);
56 |
57 | float wc = 1. - dot(1., w0 + w1); // compensate truncated window factor by linear factoring on the two nearest samples
58 | w0.z += wc * (1. - t);
59 | w1.x += wc * t;
60 |
61 | return w0.x * Q0 + w0.y * Q1 + w0.z * Q2 + w1.x * Q3 + w1.y * Q4 + w1.z * Q5; // interpolation output
62 | }
63 |
64 | return Q2; // case t == 0. is required to return sample Q2, because of a possible division by 0.
65 | }
66 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_interpolation_spline4.hlsl:
--------------------------------------------------------------------------------
1 | #ifndef AXIS
2 | #define AXIS 0
3 | #endif
4 |
5 | #ifndef METHOD
6 | #define METHOD 1
7 | #endif
8 |
9 | Texture2D tex : register(t0);
10 | SamplerState samp : register(s0);
11 |
12 | cbuffer PS_CONSTANTS : register(b0)
13 | {
14 | float2 wh;
15 | float2 dxdy;
16 | float2 scale;
17 | };
18 |
19 | struct PS_INPUT
20 | {
21 | float4 Pos : SV_POSITION;
22 | float2 Tex : TEXCOORD;
23 | };
24 |
25 | float4 main(PS_INPUT input) : SV_Target
26 | {
27 | float pos = input.Tex[AXIS] * wh[AXIS] - 0.5;
28 | float t = frac(pos); // calculate the difference between the output pixel and the original surrounding two pixels
29 | pos = pos - t;
30 |
31 | #if (AXIS == 0)
32 | // original pixels
33 | float4 Q0 = tex.Sample(samp, float2((pos - 0.5) * dxdy.x, input.Tex.y));
34 | float4 Q1 = tex.Sample(samp, float2((pos + 0.5) * dxdy.x, input.Tex.y));
35 | float4 Q2 = tex.Sample(samp, float2((pos + 1.5) * dxdy.x, input.Tex.y));
36 | float4 Q3 = tex.Sample(samp, float2((pos + 2.5) * dxdy.x, input.Tex.y));
37 | #elif (AXIS == 1)
38 | // original pixels
39 | float4 Q0 = tex.Sample(samp, float2(input.Tex.x, (pos - 0.5) * dxdy.y));
40 | float4 Q1 = tex.Sample(samp, float2(input.Tex.x, (pos + 0.5) * dxdy.y));
41 | float4 Q2 = tex.Sample(samp, float2(input.Tex.x, (pos + 1.5) * dxdy.y));
42 | float4 Q3 = tex.Sample(samp, float2(input.Tex.x, (pos + 2.5) * dxdy.y));
43 | #else
44 | #error ERROR: incorrect AXIS.
45 | #endif
46 |
47 | // calculate weights
48 | float t2 = t * t;
49 | float t3 = t * t2;
50 | #if (METHOD == 0) // Mitchell-Netravali spline4
51 | float4 w0123 = float4(1., 16., 1., 0.)/18.+float4(-.5, 0., .5, 0.)*t+float4(5., -12., 9., -2.)/6.*t2+float4(-7., 21., -21., 7.)/18.*t3;
52 | #elif (METHOD == 1) // Catmull-Rom spline4
53 | float4 w0123 = float4(-.5, 0., .5, 0.)*t+float4(1., -2.5, 2., -.5)*t2+float4(-.5, 1.5, -1.5, .5)*t3;
54 | w0123.y += 1.;
55 | #else
56 | #error ERROR: incorrect METHOD.
57 | #endif
58 |
59 | return w0123[0] * Q0 + w0123[1] * Q1 + w0123[2] * Q2 + w0123[3] * Q3; // interpolation output
60 | }
61 |
--------------------------------------------------------------------------------
/Shaders/d3d11/ps_simple.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D tex : register(t0);
2 | SamplerState samp : register(s0);
3 |
4 | struct PS_INPUT
5 | {
6 | float4 Pos : SV_POSITION;
7 | float2 Tex : TEXCOORD;
8 | };
9 |
10 | float4 main(PS_INPUT input) : SV_Target
11 | {
12 | return tex.Sample(samp, input.Tex);
13 | }
14 |
--------------------------------------------------------------------------------
/Shaders/d3d11/vs_geometry.hlsl:
--------------------------------------------------------------------------------
1 | // vertex shader for D3D11Geometry
2 | struct VS_INPUT
3 | {
4 | float4 position : POSITION;
5 | float4 color : COLOR;
6 | };
7 |
8 | struct VS_OUTPUT
9 | {
10 | float4 position : SV_POSITION;
11 | float4 color : COLOR;
12 | };
13 |
14 | VS_OUTPUT main(VS_INPUT input)
15 | {
16 | return input;
17 | }
18 |
--------------------------------------------------------------------------------
/Shaders/d3d11/vs_simple.hlsl:
--------------------------------------------------------------------------------
1 | struct VS_INPUT
2 | {
3 | float4 Pos : POSITION;
4 | float2 Tex : TEXCOORD;
5 | };
6 |
7 | struct VS_OUTPUT
8 | {
9 | float4 Pos : SV_POSITION;
10 | float2 Tex : TEXCOORD;
11 | };
12 |
13 | VS_OUTPUT main(VS_INPUT input)
14 | {
15 | return input;
16 | }
17 |
--------------------------------------------------------------------------------
/Shaders/d3d9/convert_biplanar.hlsl:
--------------------------------------------------------------------------------
1 | sampler sY : register(s0);
2 | sampler sUV : register(s1);
3 |
4 | float4 cm_r : register(c0);
5 | float4 cm_g : register(c1);
6 | float4 cm_b : register(c2);
7 | float3 cm_c : register(c3);
8 |
9 | float4 main(float2 tex : TEXCOORD0) : COLOR
10 | {
11 | float colorY = tex2D(sY, tex).r;
12 | float3 colorUV = tex2D(sUV, tex).rga; // for D3DFMT_G16R16 and D3DFMT_A8L8 variants
13 |
14 | float4 color = float4(colorY, colorUV);
15 |
16 | color.rgb = float3(mul(cm_r, color), mul(cm_g, color), mul(cm_b, color)) + cm_c;
17 |
18 | return color;
19 | }
20 |
--------------------------------------------------------------------------------
/Shaders/d3d9/convert_color.hlsl:
--------------------------------------------------------------------------------
1 | #ifndef C_YUY2
2 | #define C_YUY2 0
3 | #endif
4 |
5 | sampler s0 : register(s0);
6 |
7 | float3 cm_r : register(c0);
8 | float3 cm_g : register(c1);
9 | float3 cm_b : register(c2);
10 | float3 cm_c : register(c3);
11 |
12 | #if C_YUY2
13 | float4 p4 : register(c4);
14 | #define width (p4[0])
15 | #define height (p4[1])
16 | #define dx (p4[2])
17 | #define dy (p4[3])
18 | #endif
19 |
20 | float4 main(float2 tex : TEXCOORD0) : COLOR
21 | {
22 | float4 color = tex2D(s0, tex); // original pixel
23 |
24 | #if C_YUY2
25 | if (fmod(tex.x*width, 2) < 1.0) {
26 | // used D3DFMT_A8R8G8B8 is used because D3DFMT_A8B8G8R8 cannot be used on some video cards
27 | color = float4(color[2], color[1], color[3], 0);
28 | } else {
29 | #if (C_YUY2 == 1) // nearest neighbor
30 | color = float4(color[0], color[1], color[3], 0);
31 | #elif (C_YUY2 == 2) // linear
32 | float2 chroma0 = color.yw;
33 | float2 chroma1 = tex2D(s0, tex + float2(dx, 0)).yw;
34 | float2 chroma = (chroma0 + chroma1) * 0.5;
35 | color = float4(color[0], chroma, 0);
36 | #elif (C_YUY2 == 3) // cubic
37 | float2 chroma0 = tex2D(s0, tex + float2(-dx, 0)).yw;
38 | float2 chroma1 = color.yw;
39 | float2 chroma2 = tex2D(s0, tex + float2(dx, 0)).yw;
40 | float2 chroma3 = tex2D(s0, tex + float2(2*dx, 0)).yw;
41 | float2 chroma = (9 * (chroma1 + chroma2) - (chroma0 + chroma3)) * 0.0625;
42 | color = float4(color[0], chroma, 0);
43 | #endif
44 | }
45 | #endif
46 |
47 | color.rgb = float3(mul(cm_r, color.rgb), mul(cm_g, color.rgb), mul(cm_b, color.rgb)) + cm_c;
48 |
49 | return color;
50 | }
51 |
--------------------------------------------------------------------------------
/Shaders/d3d9/convert_planar.hlsl:
--------------------------------------------------------------------------------
1 | sampler sY : register(s0);
2 | sampler sU : register(s1);
3 | sampler sV : register(s2);
4 |
5 | float4 cm_r : register(c0);
6 | float4 cm_g : register(c1);
7 | float4 cm_b : register(c2);
8 | float3 cm_c : register(c3);
9 |
10 | float4 main(float2 tex : TEXCOORD0) : COLOR
11 | {
12 | float colorY = tex2D(sY, tex).r;
13 | float colorU = tex2D(sU, tex).r;
14 | float colorV = tex2D(sV, tex).r;
15 |
16 | float4 color = float4(colorY, colorU, colorV, 0);
17 |
18 | color.rgb = float3(mul(cm_r, color), mul(cm_g, color), mul(cm_b, color)) + cm_c;
19 |
20 | return color;
21 | }
22 |
--------------------------------------------------------------------------------
/Shaders/d3d9/convert_planar_yv.hlsl:
--------------------------------------------------------------------------------
1 | sampler sY : register(s0);
2 | sampler sV : register(s1);
3 | sampler sU : register(s2);
4 |
5 | float4 cm_r : register(c0);
6 | float4 cm_g : register(c1);
7 | float4 cm_b : register(c2);
8 | float3 cm_c : register(c3);
9 |
10 | float4 main(float2 tex : TEXCOORD0) : COLOR
11 | {
12 | float colorY = tex2D(sY, tex).r;
13 | float colorU = tex2D(sU, tex).r;
14 | float colorV = tex2D(sV, tex).r;
15 |
16 | float4 color = float4(colorY, colorU, colorV, 0);
17 |
18 | color.rgb = float3(mul(cm_r, color), mul(cm_g, color), mul(cm_b, color)) + cm_c;
19 |
20 | return color;
21 | }
22 |
--------------------------------------------------------------------------------
/Shaders/d3d9/convolution.hlsl:
--------------------------------------------------------------------------------
1 |
2 | sampler s0 : register(s0); // input texture
3 | float2 dxdy : register(c0);
4 | float2 scale : register(c1);
5 |
6 | #include "../resize/convolution_filters.hlsl"
7 |
8 | #ifndef AXIS
9 | #define AXIS 0
10 | #endif
11 |
12 | static const float support = filter_support * scale[AXIS];
13 | static const float ss = 1.0 / scale[AXIS];
14 |
15 | float4 main ( float2 tex : TEXCOORD0 ) : COLOR
16 | {
17 | tex += 0.5;
18 |
19 | int low = (int)floor(tex[AXIS] - support);
20 | int high = (int)ceil(tex[AXIS] + support);
21 |
22 | float ww = 0.0;
23 | float4 avg = 0;
24 |
25 | [loop] for (int n = low; n < high; n++) {
26 | float w = filter((n - tex[AXIS] + 0.5) * ss);
27 | ww += w;
28 | #if (AXIS == 0)
29 | avg += w * tex2D(s0, (tex + float2(n - tex[AXIS] + 0.5, 0)) * dxdy, 0, 0);
30 | #else
31 | avg += w * tex2D(s0, (tex + float2(0, n - tex[AXIS] + 0.5)) * dxdy, 0, 0);
32 | #endif
33 | }
34 | avg /= ww;
35 |
36 | return avg;
37 | }
38 |
--------------------------------------------------------------------------------
/Shaders/d3d9/final_pass.hlsl:
--------------------------------------------------------------------------------
1 |
2 | #ifndef QUANTIZATION
3 | // 255 or 1023 (Maximum quantized integer value)
4 | #define QUANTIZATION 255
5 | #endif
6 |
7 | sampler image : register(s0);
8 | sampler ditherMatrix : register(s1);
9 | float2 ditherMatrixCoordScale : register(c0);
10 |
11 | float4 main(float2 imageCoord : TEXCOORD0) : COLOR
12 | {
13 | float4 pixel = tex2D(image, imageCoord);
14 |
15 | float4 ditherValue = tex2D(ditherMatrix, imageCoord * ditherMatrixCoordScale);
16 | pixel = floor(pixel * QUANTIZATION + ditherValue) / QUANTIZATION;
17 |
18 | return pixel;
19 | };
20 |
--------------------------------------------------------------------------------
/Shaders/d3d9/fix_bt2020.hlsl:
--------------------------------------------------------------------------------
1 | sampler s0 : register(s0);
2 |
3 | #include "../convert/conv_matrix.hlsl"
4 | #include "../convert/colorspace_gamut_conversion.hlsl"
5 |
6 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);
7 |
8 | float4 main(float2 tex : TEXCOORD0) : COLOR
9 | {
10 | float4 color = tex2D(s0, tex);
11 |
12 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in DXVA2 VP
13 | color = mul(fix_bt2020_matrix, color);
14 |
15 | // sRGB to Linear
16 | color = saturate(color);
17 | color = pow(color, 2.2);
18 |
19 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
20 |
21 | // Linear to sRGB
22 | color = saturate(color);
23 | color = pow(color, 1.0 / 2.2);
24 |
25 | return color;
26 | }
27 |
--------------------------------------------------------------------------------
/Shaders/d3d9/fix_ycgco.hlsl:
--------------------------------------------------------------------------------
1 | sampler s0 : register(s0);
2 |
3 | #include "../convert/conv_matrix.hlsl"
4 |
5 | static const float4x4 fix_ycgco_matrix = mul(ycgco_rgb, rgb_ycbcr709);
6 |
7 | float4 main(float2 tex : TEXCOORD0) : COLOR
8 | {
9 | float4 pixel = tex2D(s0, tex); // original pixel
10 |
11 | // Fix incorrect (unsupported) conversion from YCgCo to RGB in DXVA2 VP
12 | pixel = mul(fix_ycgco_matrix, pixel);
13 |
14 | return pixel;
15 | }
16 |
--------------------------------------------------------------------------------
/Shaders/d3d9/fixconvert_hlg_to_sdr.hlsl:
--------------------------------------------------------------------------------
1 | sampler s0 : register(s0);
2 | float4 parameters : register(c0);
3 | #define LuminanceScale parameters[0]
4 | #define param2 parameters[1]
5 |
6 | #include "../convert/conv_matrix.hlsl"
7 | #include "../convert/hlg.hlsl"
8 | #include "../convert/st2084.hlsl"
9 | #include "../convert/hdr_tone_mapping.hlsl"
10 | #include "../convert/colorspace_gamut_conversion.hlsl"
11 |
12 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);
13 |
14 | float4 main(float2 tex : TEXCOORD0) : COLOR
15 | {
16 | float4 color = tex2D(s0, tex); // original pixel
17 |
18 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in DXVA2 VP
19 | color = mul(fix_bt2020_matrix, color);
20 |
21 | // HLG to PQ
22 | color = saturate(color);
23 | color.rgb = HLGtoLinear(color.rgb);
24 | color = LinearToST2084(color, 1000.0);
25 |
26 | // PQ to Linear
27 | color = saturate(color);
28 | color = ST2084ToLinear(color, LuminanceScale);
29 |
30 | color.rgb = ToneMappingHable(color.rgb);
31 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
32 |
33 | // Linear to sRGB
34 | color = saturate(color);
35 | color = pow(color, 1.0 / 2.2);
36 |
37 | return color;
38 | }
39 |
--------------------------------------------------------------------------------
/Shaders/d3d9/fixconvert_pq_to_sdr.hlsl:
--------------------------------------------------------------------------------
1 | sampler s0 : register(s0);
2 | float4 parameters : register(c0);
3 | #define LuminanceScale parameters[0]
4 | #define param2 parameters[1]
5 |
6 | #include "../convert/conv_matrix.hlsl"
7 | #include "../convert/st2084.hlsl"
8 | #include "../convert/hdr_tone_mapping.hlsl"
9 | #include "../convert/colorspace_gamut_conversion.hlsl"
10 |
11 | static const float4x4 fix_bt2020_matrix = mul(ycbcr2020nc_rgb, rgb_ycbcr709);
12 |
13 | float4 main(float2 tex : TEXCOORD0) : COLOR
14 | {
15 | float4 color = tex2D(s0, tex); // original pixel
16 |
17 | // Fix incorrect (unsupported) conversion from YCbCr BT.2020 to RGB in DXVA2 VP
18 | color = mul(fix_bt2020_matrix, color);
19 |
20 | // PQ to Linear
21 | color = saturate(color);
22 | color = ST2084ToLinear(color, LuminanceScale);
23 |
24 | color.rgb = ToneMappingHable(color.rgb);
25 | color.rgb = Colorspace_Gamut_Conversion_2020_to_709(color.rgb);
26 |
27 | // Linear to sRGB
28 | color = saturate(color);
29 | color = pow(color, 1.0 / 2.2);
30 |
31 | return color;
32 | }
33 |
--------------------------------------------------------------------------------
/Shaders/d3d9/halfoverunder_to_interlace.hlsl:
--------------------------------------------------------------------------------
1 | // convert Half OverUnder to Interlace
2 |
3 | sampler s0 : register(s0);
4 | float4 p0 : register(c0);
5 |
6 | #define height (p0[0])
7 | #define dtop (p0[2])
8 | #define dbottom (p0[3])
9 |
10 | float4 main(float2 tex : TEXCOORD0) : COLOR
11 | {
12 | if (tex.y >= dbottom) {
13 | return float4(0.0, 0.0, 0.0, 1.0);
14 | }
15 |
16 | if (fmod((tex.y - dtop) * height, 2) < 1.0) {
17 | // even
18 | tex.y = (dtop + tex.y) / 2;
19 | } else {
20 | // odd
21 | tex.y = (dbottom + tex.y) / 2;
22 | }
23 |
24 | return tex2D(s0, tex);
25 | }
26 |
--------------------------------------------------------------------------------
/Shaders/d3d9/interpolation_lanczos2.hlsl:
--------------------------------------------------------------------------------
1 | // compensated Lanczos2
2 |
3 | #ifndef AXIS
4 | #define AXIS 0
5 | #endif
6 |
7 | #define PI acos(-1.)
8 |
9 | sampler s0 : register(s0);
10 | float2 dxdy : register(c0);
11 |
12 | float4 main(float2 tex : TEXCOORD0) : COLOR
13 | {
14 | float t = frac(tex[AXIS]);
15 | #if (AXIS == 0)
16 | float2 pos = tex-float2(t, 0.);
17 | #elif (AXIS == 1)
18 | float2 pos = tex-float2(0., t);
19 | #else
20 | #error ERROR: incorrect AXIS.
21 | #endif
22 |
23 | float4 Q1 = tex2D(s0, (pos+.5)*dxdy); // nearest original pixel to the left
24 | if(t) {
25 | // original pixels
26 | #if (AXIS == 0)
27 | float4 Q0 = tex2D(s0, (pos+float2(-.5, .5))*dxdy);
28 | float4 Q2 = tex2D(s0, (pos+float2(1.5, .5))*dxdy);
29 | float4 Q3 = tex2D(s0, (pos+float2(2.5, .5))*dxdy);
30 | #elif (AXIS == 1)
31 | float4 Q0 = tex2D(s0, (pos+float2(.5, -.5))*dxdy);
32 | float4 Q2 = tex2D(s0, (pos+float2(.5, 1.5))*dxdy);
33 | float4 Q3 = tex2D(s0, (pos+float2(.5, 2.5))*dxdy);
34 | #endif
35 | float4 wset = float3(0., 1., 2.).yxyz+float2(t, -t).xxyy;
36 | float4 w = sin(wset*PI)*sin(wset*PI*.5)/(wset*wset*PI*PI*.5);
37 |
38 | float wc = 1.-dot(1., w); // compensate truncated window factor by bilinear factoring on the two nearest samples
39 | w.y += wc*(1.-t);
40 | w.z += wc*t;
41 |
42 | return w.x*Q0+w.y*Q1+w.z*Q2+w.w*Q3; // interpolation output
43 | }
44 |
45 | return Q1; // case t == 0. is required to return sample Q1, because of a possible division by 0.
46 | }
47 |
--------------------------------------------------------------------------------
/Shaders/d3d9/interpolation_lanczos3.hlsl:
--------------------------------------------------------------------------------
1 | // compensated Lanczos3
2 |
3 | #ifndef AXIS
4 | #define AXIS 0
5 | #endif
6 |
7 | #define PI acos(-1.)
8 |
9 | sampler s0 : register(s0);
10 | float2 dxdy : register(c0);
11 |
12 | float4 main(float2 tex : TEXCOORD0) : COLOR
13 | {
14 | float t = frac(tex[AXIS]);
15 | #if (AXIS == 0)
16 | float2 pos = tex - float2(t, 0.);
17 | #elif (AXIS == 1)
18 | float2 pos = tex-float2(0., t);
19 | #else
20 | #error ERROR: incorrect AXIS.
21 | #endif
22 |
23 | float4 Q2 = tex2D(s0, (pos+.5)*dxdy); // nearest original pixel to the left
24 | if(!t) return Q2; // case t == 0. is required to return sample Q2, because of a possible division by 0.
25 | else {
26 | // original pixels
27 | #if (AXIS == 0)
28 | float4 Q0 = tex2D(s0, (pos+float2(-1.5, .5))*dxdy);
29 | float4 Q1 = tex2D(s0, (pos+float2(-.5, .5))*dxdy);
30 | float4 Q3 = tex2D(s0, (pos+float2(1.5, .5))*dxdy);
31 | float4 Q4 = tex2D(s0, (pos+float2(2.5, .5))*dxdy);
32 | float4 Q5 = tex2D(s0, (pos+float2(3.5, .5))*dxdy);
33 | #elif (AXIS == 1)
34 | float4 Q0 = tex2D(s0, (pos+float2(.5, -1.5))*dxdy);
35 | float4 Q1 = tex2D(s0, (pos+float2(.5, -.5))*dxdy);
36 | float4 Q3 = tex2D(s0, (pos+float2(.5, 1.5))*dxdy);
37 | float4 Q4 = tex2D(s0, (pos+float2(.5, 2.5))*dxdy);
38 | float4 Q5 = tex2D(s0, (pos+float2(.5, 3.5))*dxdy);
39 | #endif
40 | float3 wset0 = float3(2., 1., 0.)*PI+t*PI;
41 | float3 wset1 = float3(1., 2., 3.)*PI-t*PI;
42 | float3 wset0s = wset0*.5;
43 | float3 wset1s = wset1*.5;
44 | float3 w0 = sin(wset0)*sin(wset0s)/(wset0*wset0s);
45 | float3 w1 = sin(wset1)*sin(wset1s)/(wset1*wset1s);
46 |
47 | float wc = 1.-dot(1., w0+w1); // compensate truncated window factor by linear factoring on the two nearest samples
48 | w0.z += wc*(1.-t);
49 | w1.x += wc*t;
50 |
51 | return w0.x*Q0+w0.y*Q1+w0.z*Q2+w1.x*Q3+w1.y*Q4+w1.z*Q5; // interpolation output
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Shaders/d3d9/interpolation_spline4.hlsl:
--------------------------------------------------------------------------------
1 | #ifndef AXIS
2 | #define AXIS 0
3 | #endif
4 |
5 | #ifndef METHOD
6 | #define METHOD 1
7 | #endif
8 |
9 | sampler s0 : register(s0);
10 | float2 dxdy : register(c0);
11 |
12 | float4 main(float2 tex : TEXCOORD0) : COLOR
13 | {
14 | float t = frac(tex[AXIS]);
15 | #if (AXIS == 0)
16 | float2 pos = tex-float2(t, 0.);
17 | // original pixels
18 | float4 Q0 = tex2D(s0, (pos+float2(-.5, .5))*dxdy);
19 | float4 Q1 = tex2D(s0, (pos+.5)*dxdy);
20 | float4 Q2 = tex2D(s0, (pos+float2(1.5, .5))*dxdy);
21 | float4 Q3 = tex2D(s0, (pos+float2(2.5, .5))*dxdy);
22 | #elif (AXIS == 1)
23 | float2 pos = tex-float2(0., t);
24 | // original pixels
25 | float4 Q0 = tex2D(s0, (pos+float2(.5, -.5))*dxdy);
26 | float4 Q1 = tex2D(s0, (pos+.5)*dxdy);
27 | float4 Q2 = tex2D(s0, (pos+float2(.5, 1.5))*dxdy);
28 | float4 Q3 = tex2D(s0, (pos+float2(.5, 2.5))*dxdy);
29 | #else
30 | #error ERROR: incorrect AXIS.
31 | #endif
32 |
33 | // calculate weights
34 | float t2 = t * t;
35 | float t3 = t * t2;
36 | #if (METHOD == 0) // Mitchell-Netravali spline4
37 | float4 w0123 = float4(1., 16., 1., 0.)/18.+float4(-.5, 0., .5, 0.)*t+float4(5., -12., 9., -2.)/6.*t2+float4(-7., 21., -21., 7.)/18.*t3;
38 | #elif (METHOD == 1) // Catmull-Rom spline4
39 | float4 w0123 = float4(-.5, 0., .5, 0.)*t+float4(1., -2.5, 2., -.5)*t2+float4(-.5, 1.5, -1.5, .5)*t3;
40 | w0123.y += 1.;
41 | #else
42 | #error ERROR: incorrect METHOD.
43 | #endif
44 |
45 | return w0123[0] * Q0 + w0123[1] * Q1 + w0123[2] * Q2 + w0123[3] * Q3; // interpolation output
46 | }
47 |
--------------------------------------------------------------------------------
/Shaders/examples/ps_mpv.hlsl:
--------------------------------------------------------------------------------
1 | // based on blit_float_ps from code of mpv
2 | // also see
3 | // static void pass_convert_yuv
4 | // void pass_color_map
5 |
6 | Texture2D tex : register(t0);
7 | SamplerState samp : register(s0);
8 |
9 | float4 main(float4 pos : SV_Position, float2 coord : TEXCOORD0) : SV_Target
10 | {
11 | return tex.Sample(samp, coord);
12 | }
13 |
--------------------------------------------------------------------------------
/Shaders/examples/ps_resize_onepass_bilinear.hlsl:
--------------------------------------------------------------------------------
1 | // Bilinear
2 |
3 | Texture2D tex : register(t0);
4 | SamplerState samp : register(s0);
5 |
6 | cbuffer PS_WH : register(b0)
7 | {
8 | float2 wh;
9 | float2 dxdy;
10 | };
11 |
12 | struct PS_INPUT
13 | {
14 | float4 Pos : SV_POSITION;
15 | float2 Tex : TEXCOORD;
16 | };
17 |
18 | float4 main(PS_INPUT input) : SV_Target
19 | {
20 | float2 pos = (input.Tex) * wh - 0.5;
21 | float2 t = frac(pos);
22 | pos = (pos - t + 0.5) * dxdy;
23 |
24 | float4 c00 = tex.Sample(samp, pos);
25 | float4 c01 = tex.Sample(samp, pos + dxdy * float2(0, 1));
26 | float4 c10 = tex.Sample(samp, pos + dxdy * float2(1, 0));
27 | float4 c11 = tex.Sample(samp, pos + dxdy);
28 |
29 | return lerp(
30 | lerp(c00, c10, t.x),
31 | lerp(c01, c11, t.x),
32 | t.y); // interpolate and output
33 | }
34 |
--------------------------------------------------------------------------------
/Shaders/examples/ps_resize_onepass_catmull4.hlsl:
--------------------------------------------------------------------------------
1 | // Catmull-Rom spline4
2 |
3 | Texture2D tex : register(t0);
4 | SamplerState samp : register(s0);
5 |
6 | cbuffer PS_WH : register(b0)
7 | {
8 | float2 wh;
9 | float2 dxdy;
10 | };
11 |
12 | struct PS_INPUT
13 | {
14 | float4 Pos : SV_POSITION;
15 | float2 Tex : TEXCOORD;
16 | };
17 |
18 | #define sp(a, b, c) float4 a = tex.Sample(samp, pos + dxdy*float2(b, c))
19 |
20 | float4 main(PS_INPUT input) : SV_Target
21 | {
22 | float2 pos = (input.Tex) * wh - 0.5;
23 | float2 t = frac(pos); // calculate the difference between the output pixel and the original surrounding two pixels
24 | pos = (pos - t + 0.5) * dxdy; // adjust sampling matrix to put the output pixel in the interval [Q1, Q2)
25 |
26 | // weights
27 | float2 t2 = t * t;
28 | float2 t3 = t * t2;
29 | float2 w0 = t2 - (t3 + t) / 2;
30 | float2 w1 = t3 * 1.5 + 1 - t2 * 2.5;
31 | float2 w2 = t2 * 2 + t / 2 - t3 * 1.5;
32 | float2 w3 = (t3 - t2) / 2;
33 |
34 | // original pixels
35 | sp(M0, -1, -1); sp(M1, -1, 0); sp(M2, -1, 1); sp(M3, -1, 2);
36 | sp(L0, 0, -1); sp(L1, 0, 0); sp(L2, 0, 1); sp(L3, 0, 2);
37 | sp(K0, 1, -1); sp(K1, 1, 0); sp(K2, 1, 1); sp(K3, 1, 2);
38 | sp(J0, 2, -1); sp(J1, 2, 0); sp(J2, 2, 1); sp(J3, 2, 2);
39 |
40 | // vertical interpolation
41 | float4 Q0 = M0 * w0.y + M1 * w1.y + M2 * w2.y + M3 * w3.y;
42 | float4 Q1 = L0 * w0.y + L1 * w1.y + L2 * w2.y + L3 * w3.y;
43 | float4 Q2 = K0 * w0.y + K1 * w1.y + K2 * w2.y + K3 * w3.y;
44 | float4 Q3 = J0 * w0.y + J1 * w1.y + J2 * w2.y + J3 * w3.y;
45 |
46 | return Q0 * w0.x + Q1 * w1.x + Q2 * w2.x + Q3 * w3.x; // horizontal interpolation and output
47 | }
48 |
--------------------------------------------------------------------------------
/Shaders/examples/ps_resize_onepass_jinc2.hlsl:
--------------------------------------------------------------------------------
1 | // jinc 2
2 |
3 | Texture2D tex : register(t0);
4 | SamplerState samp : register(s0);
5 |
6 | cbuffer PS_WH : register(b0)
7 | {
8 | float2 wh;
9 | float2 dxdy;
10 | };
11 |
12 | struct PS_INPUT
13 | {
14 | float4 Pos : SV_POSITION;
15 | float2 Tex : TEXCOORD;
16 | };
17 |
18 | #define JINC2_WINDOW_SINC 0.416
19 | #define JINC2_SINC 0.985
20 | #define JINC2_AR_STRENGTH 0.8
21 | #define JINC2_AR_ENABLE 1
22 |
23 | static const float pi = acos(-1);
24 | static const float wa = JINC2_WINDOW_SINC * pi;
25 | static const float wb = JINC2_SINC * pi;
26 |
27 | #define min4(a, b, c, d) min(min(min(a, b), c), d)
28 | #define max4(a, b, c, d) max(max(max(a, b), c), d)
29 |
30 | // Calculates the distance between two points
31 | float d(float2 pt1, float2 pt2)
32 | {
33 | float2 v = pt2 - pt1;
34 | return sqrt(dot(v, v));
35 | }
36 |
37 | float4 resampler(float4 x)
38 | {
39 | return (x == float4(0, 0, 0, 0))
40 | ? float4(wa * wb, wa * wb, wa * wb, wa * wb)
41 | : sin(x * wa) * sin(x * wb) / (x * x);
42 | }
43 |
44 | float4 main(PS_INPUT input) : SV_Target
45 | {
46 | float2 dx = float2(1, 0);
47 | float2 dy = float2(0, 1);
48 |
49 | float2 pc = input.Tex * wh;
50 | float2 tc = floor(pc - 0.5) + 0.5;
51 |
52 | float4x4 weights = {
53 | resampler(float4(d(pc, tc - dx - dy ), d(pc, tc - dy ), d(pc, tc + dx - dy ), d(pc, tc + 2*dx - dy ))),
54 | resampler(float4(d(pc, tc - dx ), d(pc, tc ), d(pc, tc + dx ), d(pc, tc + 2*dx ))),
55 | resampler(float4(d(pc, tc - dx + dy ), d(pc, tc + dy ), d(pc, tc + dx + dy ), d(pc, tc + 2*dx + dy ))),
56 | resampler(float4(d(pc, tc - dx + 2*dy), d(pc, tc + 2*dy), d(pc, tc + dx + 2*dy), d(pc, tc + 2*dx + 2*dy)))
57 | };
58 |
59 | dx *= dxdy;
60 | dy *= dxdy;
61 | tc *= dxdy;
62 |
63 | // reading the texels
64 | // [ c00, c10, c20, c30 ]
65 | // [ c01, c11, c21, c31 ]
66 | // [ c02, c12, c22, c32 ]
67 | // [ c03, c13, c23, c33 ]
68 | float3 c00 = tex.Sample(samp, tc - dx - dy ).rgb;
69 | float3 c10 = tex.Sample(samp, tc - dy ).rgb;
70 | float3 c20 = tex.Sample(samp, tc + dx - dy ).rgb;
71 | float3 c30 = tex.Sample(samp, tc + 2*dx - dy ).rgb;
72 | float3 c01 = tex.Sample(samp, tc - dx ).rgb;
73 | float3 c11 = tex.Sample(samp, tc ).rgb;
74 | float3 c21 = tex.Sample(samp, tc + dx ).rgb;
75 | float3 c31 = tex.Sample(samp, tc + 2*dx ).rgb;
76 | float3 c02 = tex.Sample(samp, tc - dx + dy ).rgb;
77 | float3 c12 = tex.Sample(samp, tc + dy ).rgb;
78 | float3 c22 = tex.Sample(samp, tc + dx + dy ).rgb;
79 | float3 c32 = tex.Sample(samp, tc + 2*dx + dy ).rgb;
80 | float3 c03 = tex.Sample(samp, tc - dx + 2*dy).rgb;
81 | float3 c13 = tex.Sample(samp, tc + 2*dy).rgb;
82 | float3 c23 = tex.Sample(samp, tc + dx + 2*dy).rgb;
83 | float3 c33 = tex.Sample(samp, tc + 2*dx + 2*dy).rgb;
84 |
85 | float3 color = mul(weights[0], float4x3(c00, c10, c20, c30));
86 | color += mul(weights[1], float4x3(c01, c11, c21, c31));
87 | color += mul(weights[2], float4x3(c02, c12, c22, c32));
88 | color += mul(weights[3], float4x3(c03, c13, c23, c33));
89 | color /= dot(mul(weights, float4(1, 1, 1, 1)), 1);
90 |
91 | #if JINC2_AR_ENABLE
92 | // calc min/max samples
93 | float3 min_sample = min4(c11, c21, c12, c22);
94 | float3 max_sample = max4(c11, c21, c12, c22);
95 |
96 | // Anti-ringing
97 | color = lerp(color, clamp(color, min_sample, max_sample), JINC2_AR_STRENGTH);
98 | #endif
99 |
100 | return float4(color, 1);
101 | }
102 |
--------------------------------------------------------------------------------
/Shaders/examples/ps_vlc.hlsl:
--------------------------------------------------------------------------------
1 | // based on globPixelShaderDefault from code of VLC
2 |
3 | #define LEGACY_SHADER_MODE 1
4 |
5 | cbuffer PS_CONSTANT_BUFFER : register(b0)
6 | {
7 | float Opacity;
8 | float BoundaryX;
9 | float BoundaryY;
10 | float LuminanceScale;
11 | };
12 | cbuffer PS_COLOR_TRANSFORM : register(b1)
13 | {
14 | float4x4 WhitePoint;
15 | float4x4 Colorspace;
16 | float4x4 Primaries;
17 | };
18 | #if LEGACY_SHADER_MODE
19 | Texture2D shaderTexture[4];
20 | #else
21 | Texture2DArray shaderTexture[4];
22 | #endif
23 | SamplerState SamplerStates[2];
24 |
25 | struct PS_INPUT
26 | {
27 | float4 Position : SV_POSITION;
28 | float3 Texture : TEXCOORD0;
29 | };
30 |
31 | /* see http://filmicworlds.com/blog/filmic-tonemapping-operators/ */
32 | inline float4 hable(float4 x) {
33 | const float A = 0.15, B = 0.50, C = 0.10, D = 0.20, E = 0.02, F = 0.30;
34 | return ((x * (A*x + (C*B))+(D*E))/(x * (A*x + B) + (D*F))) - E/F;
35 | }
36 |
37 | /* https://en.wikipedia.org/wiki/Hybrid_Log-Gamma#Technical_details */
38 | inline float inverse_HLG(float x){
39 | const float B67_a = 0.17883277;
40 | const float B67_b = 0.28466892;
41 | const float B67_c = 0.55991073;
42 | const float B67_inv_r2 = 4.0; /* 1/0.5² */
43 | if (x <= 0.5)
44 | x = x * x * B67_inv_r2;
45 | else
46 | x = exp((x - B67_c) / B67_a) + B67_b;
47 | return x;
48 | }
49 |
50 | inline float4 sourceToLinear(float4 rgb) {
51 | return rgb;
52 | }
53 |
54 | inline float4 linearToDisplay(float4 rgb) {
55 | return rgb;
56 | }
57 |
58 | inline float4 transformPrimaries(float4 rgb) {
59 | return rgb;
60 | }
61 |
62 | inline float4 toneMapping(float4 rgb) {
63 | return rgb;
64 | }
65 |
66 | inline float4 adjustRange(float4 rgb) {
67 | return rgb;
68 | }
69 |
70 | inline float4 sampleTexture(SamplerState samplerState, float3 coords) {
71 | float4 sample;
72 | #if LEGACY_SHADER_MODE
73 | sample = shaderTexture[0].Sample(samplerState, coords.xy); /* sampling routine in sample */
74 | #else
75 | sample = shaderTexture[0].Sample(samplerState, coords); /* sampling routine in sample */
76 | #endif
77 | return sample;
78 | }
79 |
80 | float4 main( PS_INPUT In ) : SV_TARGET
81 | {
82 | float4 sample;
83 |
84 | if (In.Texture.x > BoundaryX || In.Texture.y > BoundaryY)
85 | sample = sampleTexture( SamplerStates[1], In.Texture );
86 | else
87 | sample = sampleTexture( SamplerStates[0], In.Texture );
88 | float4 rgba = max(mul(mul(sample, WhitePoint), Colorspace),0);
89 | float opacity = rgba.a * Opacity;
90 | float4 rgb = rgba; rgb.a = 0;
91 | rgb = sourceToLinear(rgb);
92 | rgb = transformPrimaries(rgb);
93 | rgb = toneMapping(rgb);
94 | rgb = linearToDisplay(rgb);
95 | rgb = adjustRange(rgb);
96 | return float4(rgb.rgb, saturate(opacity));
97 | }
98 |
--------------------------------------------------------------------------------
/Shaders/examples/resizer_onepass_jinc2.hlsl:
--------------------------------------------------------------------------------
1 | // jinc 2
2 |
3 | sampler s0 : register(s0); // input texture
4 | float2 dxdy : register(c0);
5 |
6 | #define JINC2_WINDOW_SINC 0.416
7 | #define JINC2_SINC 0.985
8 | #define JINC2_AR_STRENGTH 0.8
9 | #define JINC2_AR_ENABLE 1
10 |
11 | static const float pi = acos(-1);
12 | static const float wa = JINC2_WINDOW_SINC * pi;
13 | static const float wb = JINC2_SINC * pi;
14 |
15 | #define min4(a, b, c, d) min(min(min(a, b), c), d)
16 | #define max4(a, b, c, d) max(max(max(a, b), c), d)
17 |
18 | // Calculates the distance between two points
19 | float d(float2 pt1, float2 pt2)
20 | {
21 | float2 v = pt2 - pt1;
22 | return sqrt(dot(v, v));
23 | }
24 |
25 | float4 resampler(float4 x)
26 | {
27 | return (x == float4(0, 0, 0, 0))
28 | ? float4(wa * wb, wa * wb, wa * wb, wa * wb)
29 | : sin(x * wa) * sin(x * wb) / (x * x);
30 | }
31 |
32 | float4 main(float2 tex : TEXCOORD0) : COLOR
33 | {
34 | float2 dx = float2(1, 0);
35 | float2 dy = float2(0, 1);
36 |
37 | float2 pc = tex+0.5;
38 | float2 tc = floor(tex) + 0.5;
39 |
40 | float4x4 weights = {
41 | resampler(float4(d(pc, tc - dx - dy ), d(pc, tc - dy ), d(pc, tc + dx - dy ), d(pc, tc + 2*dx - dy ))),
42 | resampler(float4(d(pc, tc - dx ), d(pc, tc ), d(pc, tc + dx ), d(pc, tc + 2*dx ))),
43 | resampler(float4(d(pc, tc - dx + dy ), d(pc, tc + dy ), d(pc, tc + dx + dy ), d(pc, tc + 2*dx + dy ))),
44 | resampler(float4(d(pc, tc - dx + 2*dy), d(pc, tc + 2*dy), d(pc, tc + dx + 2*dy), d(pc, tc + 2*dx + 2*dy)))
45 | };
46 |
47 | dx *= dxdy;
48 | dy *= dxdy;
49 | tc *= dxdy;
50 |
51 | // reading the texels
52 | // [ c00, c10, c20, c30 ]
53 | // [ c01, c11, c21, c31 ]
54 | // [ c02, c12, c22, c32 ]
55 | // [ c03, c13, c23, c33 ]
56 | float3 c00 = tex2D(s0, tc - dx - dy ).rgb;
57 | float3 c10 = tex2D(s0, tc - dy ).rgb;
58 | float3 c20 = tex2D(s0, tc + dx - dy ).rgb;
59 | float3 c30 = tex2D(s0, tc + 2*dx - dy ).rgb;
60 | float3 c01 = tex2D(s0, tc - dx ).rgb;
61 | float3 c11 = tex2D(s0, tc ).rgb;
62 | float3 c21 = tex2D(s0, tc + dx ).rgb;
63 | float3 c31 = tex2D(s0, tc + 2*dx ).rgb;
64 | float3 c02 = tex2D(s0, tc - dx + dy ).rgb;
65 | float3 c12 = tex2D(s0, tc + dy ).rgb;
66 | float3 c22 = tex2D(s0, tc + dx + dy ).rgb;
67 | float3 c32 = tex2D(s0, tc + 2*dx + dy ).rgb;
68 | float3 c03 = tex2D(s0, tc - dx + 2*dy).rgb;
69 | float3 c13 = tex2D(s0, tc + 2*dy).rgb;
70 | float3 c23 = tex2D(s0, tc + dx + 2*dy).rgb;
71 | float3 c33 = tex2D(s0, tc + 2*dx + 2*dy).rgb;
72 |
73 | float3 color = mul(weights[0], float4x3(c00, c10, c20, c30));
74 | color += mul(weights[1], float4x3(c01, c11, c21, c31));
75 | color += mul(weights[2], float4x3(c02, c12, c22, c32));
76 | color += mul(weights[3], float4x3(c03, c13, c23, c33));
77 | color /= dot(mul(weights, float4(1, 1, 1, 1)), 1);
78 |
79 | #if JINC2_AR_ENABLE
80 | // calc min/max samples
81 | float3 min_sample = min4(c11, c21, c12, c22);
82 | float3 max_sample = max4(c11, c21, c12, c22);
83 |
84 | // Anti-ringing
85 | color = lerp(color, clamp(color, min_sample, max_sample), JINC2_AR_STRENGTH);
86 | #endif
87 |
88 | return float4(color, 1);
89 | }
90 |
--------------------------------------------------------------------------------
/Shaders/examples/vs_mpv.hlsl:
--------------------------------------------------------------------------------
1 | // based on blit_vs from code of mpv
2 |
3 | void main(float2 pos : POSITION, float2 coord : TEXCOORD0,
4 | out float4 out_pos : SV_Position, out float2 out_coord : TEXCOORD0)
5 | {
6 | out_pos = float4(pos, 0.0, 1.0);
7 | out_coord = coord;
8 | }
9 |
--------------------------------------------------------------------------------
/Shaders/examples/vs_vlc.hlsl:
--------------------------------------------------------------------------------
1 | // based on globVertexShaderFlat from code of VLC
2 |
3 | struct VS_INPUT
4 | {
5 | float4 Position : POSITION;
6 | float4 Texture : TEXCOORD0;
7 | };
8 |
9 | struct VS_OUTPUT
10 | {
11 | float4 Position : SV_POSITION;
12 | float4 Texture : TEXCOORD0;
13 | };
14 |
15 | VS_OUTPUT main( VS_INPUT In )
16 | {
17 | return In;
18 | }
19 |
--------------------------------------------------------------------------------
/Shaders/resize/convolution_filters.hlsl:
--------------------------------------------------------------------------------
1 | #define PI acos(-1.)
2 |
3 | #ifndef FILTER
4 | #define FILTER 2
5 | #endif
6 |
7 | #if (FILTER == 0)
8 |
9 | // box
10 | #define filter_support (0.5)
11 | inline float filter(float x)
12 | {
13 | if (x >= -0.5 && x < 0.5)
14 | return 1.0;
15 | return 0.0;
16 | }
17 |
18 | #elif (FILTER == 1)
19 |
20 | // bilinear
21 | #define filter_support (1.0)
22 | inline float filter(float x)
23 | {
24 | if (x < 0.0)
25 | x = -x;
26 | if (x < 1.0)
27 | return 1.0 - x;
28 | return 0.0;
29 | }
30 |
31 | #elif (FILTER == 2)
32 |
33 | // hamming
34 | #define filter_support (1.0)
35 | inline float filter(float x)
36 | {
37 | if (x < 0.0)
38 | x = -x;
39 | if (x == 0.0)
40 | return 1.0;
41 | if (x >= 1.0)
42 | return 0.0;
43 | x *= PI;
44 | return sin(x) / x * (0.54 + 0.46 * cos(x));
45 | }
46 |
47 | #elif (FILTER == 3)
48 |
49 | // bicubic
50 | // https://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm
51 | #ifndef A
52 | #define A -0.5
53 | #endif
54 | #define filter_support (2.0)
55 | inline float filter(float x)
56 | {
57 | if (x < 0.0)
58 | x = -x;
59 | if (x < 1.0)
60 | return ((A + 2.0) * x - (A + 3.0)) * x*x + 1;
61 | if (x < 2.0)
62 | return (((x - 5) * x + 8) * x - 4) * A;
63 | return 0.0;
64 | }
65 | #undef A
66 |
67 | #elif (FILTER == 4)
68 |
69 | // lanczos
70 | #define filter_support (3.0)
71 | inline float sinc_filter(float x)
72 | {
73 | if (x == 0.0)
74 | return 1.0;
75 | x *= PI;
76 | return sin(x) / x;
77 | }
78 | inline float filter(float x)
79 | {
80 | /* truncated sinc */
81 | if (-3.0 <= x && x < 3.0)
82 | return sinc_filter(x) * sinc_filter(x/3);
83 | return 0.0;
84 | }
85 |
86 | #endif
87 |
--------------------------------------------------------------------------------
/Source/CustomAllocator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2018-2024 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | #include
24 | #include "MediaSampleSideData.h"
25 |
26 | class CVideoRendererInputPin;
27 |
28 | class CCustomMediaSample : public CMediaSampleSideData
29 | {
30 | public:
31 | CCustomMediaSample(LPCTSTR pName, CBaseAllocator *pAllocator, HRESULT *phr, LPBYTE pBuffer, LONG length);
32 | ~CCustomMediaSample() = default;
33 |
34 | STDMETHODIMP_(ULONG) AddRef() { return __super::AddRef(); }
35 | };
36 |
37 | class CCustomAllocator : public CMemAllocator
38 | {
39 | protected:
40 | HRESULT Alloc();
41 |
42 | CVideoRendererInputPin* m_pVideoRendererInputPin = nullptr;
43 | std::unique_ptr m_pNewMT;
44 | long m_cbBuffer = 0;
45 |
46 | public:
47 | CCustomAllocator(LPCTSTR pName, LPUNKNOWN pUnk, CVideoRendererInputPin* pVideoRendererInputPin, HRESULT *phr);
48 | ~CCustomAllocator();
49 |
50 | STDMETHODIMP SetProperties(__in ALLOCATOR_PROPERTIES* pRequest, __out ALLOCATOR_PROPERTIES* pActual);
51 | STDMETHODIMP GetBuffer(IMediaSample** ppBuffer, REFERENCE_TIME* pStartTime, REFERENCE_TIME* pEndTime, DWORD dwFlags);
52 |
53 | void SetNewMediaType(const CMediaType& mt);
54 | void ClearNewMediaType();
55 | };
56 |
--------------------------------------------------------------------------------
/Source/D3DUtil/D3D11Font.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2019-2021 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | #include
24 | #include "D3DCommon.h"
25 |
26 | class CD3D11Font
27 | {
28 | // Font properties
29 | std::wstring m_strFontName;
30 | UINT m_fontHeight = 0;
31 | UINT m_fontFlags = 0;
32 |
33 | WCHAR m_Characters[128];
34 | FloatRect m_fTexCoords[128] = {};
35 | SIZE m_MaxCharMetric = {};
36 |
37 | D3DCOLOR m_Color = D3DCOLOR_XRGB(255, 255, 255);
38 |
39 | ID3D11Device* m_pDevice = nullptr;
40 | ID3D11DeviceContext* m_pDeviceContext = nullptr;
41 |
42 | ID3D11InputLayout* m_pInputLayout = nullptr;
43 | ID3D11VertexShader* m_pVertexShader = nullptr;
44 | ID3D11PixelShader* m_pPixelShader = nullptr;
45 | ID3D11Texture2D* m_pTexture = nullptr;
46 | ID3D11ShaderResourceView* m_pShaderResource = nullptr;
47 | ID3D11Buffer* m_pVertexBuffer = nullptr;
48 | //ID3D11Buffer* m_pIndexBuffer = nullptr;
49 | ID3D11Buffer* m_pPixelBuffer = nullptr;
50 | ID3D11SamplerState* m_pSamplerState = nullptr;
51 | ID3D11BlendState* m_pBlendState = nullptr;
52 |
53 | UINT m_uTexWidth = 0; // Texture dimensions
54 | UINT m_uTexHeight = 0;
55 |
56 | public:
57 | // Constructor / destructor
58 | CD3D11Font();
59 | ~CD3D11Font();
60 |
61 | // Initializing and destroying device-dependent objects
62 | HRESULT InitDeviceObjects(ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext);
63 | void InvalidateDeviceObjects();
64 |
65 | HRESULT CreateFontBitmap(const WCHAR* strFontName, const UINT fontHeight, const UINT fontFlags);
66 |
67 | SIZE GetMaxCharMetric();
68 |
69 | // Function to get extent of text
70 | HRESULT GetTextExtent(const WCHAR* strText, SIZE* pSize);
71 |
72 | // 2D text drawing function
73 | HRESULT Draw2DText(ID3D11RenderTargetView* pRenderTargetView, const SIZE& rtSize, float sx, float sy, D3DCOLOR color, const WCHAR* strText);
74 | };
75 |
--------------------------------------------------------------------------------
/Source/D3DUtil/D3D11Geometry.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2019-2020 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | struct POINTVERTEX11 {
24 | DirectX::XMFLOAT3 Pos;
25 | DirectX::XMFLOAT4 Color;
26 | };
27 |
28 | // CD3D11Quadrilateral
29 |
30 | class CD3D11Quadrilateral
31 | {
32 | protected:
33 | ID3D11Device* m_pDevice = nullptr;
34 | ID3D11DeviceContext* m_pDeviceContext = nullptr;
35 |
36 | bool m_bAlphaBlend = false;
37 | ID3D11BlendState* m_pBlendState = nullptr;
38 |
39 | POINTVERTEX11 m_Vertices[4] = {};
40 | ID3D11Buffer* m_pVertexBuffer = nullptr;
41 | ID3D11InputLayout* m_pInputLayout = nullptr;
42 |
43 | ID3D11VertexShader* m_pVertexShader = nullptr;
44 | ID3D11PixelShader* m_pPixelShader = nullptr;
45 |
46 | public:
47 | ~CD3D11Quadrilateral();
48 |
49 | HRESULT InitDeviceObjects(ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext);
50 | void InvalidateDeviceObjects();
51 |
52 | HRESULT Set(const float x1, const float y1, const float x2, const float y2, const float x3, const float y3, const float x4, const float y4, const D3DCOLOR color);
53 | HRESULT Draw(ID3D11RenderTargetView* pRenderTargetView, const SIZE& rtSize);
54 | };
55 |
56 | // CD3D11Rectangle
57 |
58 | class CD3D11Rectangle : public CD3D11Quadrilateral
59 | {
60 | private:
61 | using CD3D11Quadrilateral::Set;
62 |
63 | public:
64 | HRESULT Set(const RECT& rect, const SIZE& rtSize, const D3DCOLOR color);
65 | };
66 |
67 | // CD3D11Stripe
68 |
69 | class CD3D11Stripe : public CD3D11Quadrilateral
70 | {
71 | private:
72 | using CD3D11Quadrilateral::Set;
73 |
74 | public:
75 | HRESULT Set(const int x1, const int y1, const int x2, const int y2, const int thickness, const D3DCOLOR color);
76 | };
77 |
78 | // CD3D11Dots
79 |
80 | class CD3D11Dots
81 | {
82 | protected:
83 | ID3D11Device* m_pDevice = nullptr;
84 | ID3D11DeviceContext* m_pDeviceContext = nullptr;
85 |
86 | ID3D11InputLayout* m_pInputLayout = nullptr;
87 | ID3D11VertexShader* m_pVertexShader = nullptr;
88 | ID3D11PixelShader* m_pPixelShader = nullptr;
89 |
90 | ID3D11Buffer* m_pVertexBuffer = nullptr;
91 |
92 | SIZE m_RTSize = {};
93 | bool m_bAlphaBlend = false;
94 | std::vector m_Vertices;
95 |
96 | virtual inline bool CheckNumPoints(const UINT num)
97 | {
98 | return (num > 0);
99 | }
100 |
101 | virtual inline void DrawPrimitive()
102 | {
103 | m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
104 | m_pDeviceContext->Draw(m_Vertices.size(), 0);
105 | }
106 |
107 | public:
108 | ~CD3D11Dots();
109 |
110 | HRESULT InitDeviceObjects(ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext);
111 | void InvalidateDeviceObjects();
112 |
113 | void ClearPoints(SIZE& newRTSize);
114 | bool AddPoints(POINT* poins, const UINT size, const D3DCOLOR color);
115 | bool AddGFPoints(
116 | int Xstart, int Xstep,
117 | int Yaxis, int Yscale,
118 | int* Ydata, UINT Yoffset,
119 | const UINT size, const D3DCOLOR color);
120 |
121 | HRESULT UpdateVertexBuffer();
122 | void Draw();
123 | };
124 |
125 | // CD3D11Lines
126 |
127 | class CD3D11Lines : public CD3D11Dots
128 | {
129 | private:
130 | using CD3D11Dots::AddGFPoints;
131 |
132 | protected:
133 | inline bool CheckNumPoints(const UINT num) override
134 | {
135 | return (num >= 2 && !(num & 1));
136 | }
137 |
138 | inline void DrawPrimitive() override
139 | {
140 | m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
141 | m_pDeviceContext->Draw(m_Vertices.size(), 0);
142 | }
143 | };
144 |
145 | // CD3D9Polyline
146 |
147 | class CD3D11Polyline : public CD3D11Dots
148 | {
149 | protected:
150 | inline bool CheckNumPoints(const UINT num) override
151 | {
152 | return (num >= 2 || m_Vertices.size() && num > 0);
153 | }
154 |
155 | inline void DrawPrimitive() override
156 | {
157 | m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP);
158 | m_pDeviceContext->Draw(m_Vertices.size(), 0);
159 | }
160 | };
161 |
--------------------------------------------------------------------------------
/Source/D3DUtil/D3D9Font.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2019-2021 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | #include "D3DCommon.h"
24 |
25 | // Font rendering flags
26 | #define D3DFONT_CENTERED_X 0x0001
27 | #define D3DFONT_CENTERED_Y 0x0002
28 |
29 | class CD3D9Font
30 | {
31 | // Font properties
32 | std::wstring m_strFontName;
33 | UINT m_fontHeight = 0;
34 | UINT m_fontFlags = 0;
35 |
36 | WCHAR m_Characters[128];
37 | FloatRect m_fTexCoords[128] = {};
38 | SIZE m_MaxCharMetric = {};
39 |
40 | IDirect3DDevice9* m_pd3dDevice = nullptr; // A D3DDevice used for rendering
41 | IDirect3DTexture9* m_pTexture = nullptr; // The d3d texture for this font
42 | IDirect3DVertexBuffer9* m_pVertexBuffer = nullptr; // VertexBuffer for rendering text
43 | D3DCAPS9 m_D3DCaps = {};
44 | UINT m_uTexWidth = 0; // Texture dimensions
45 | UINT m_uTexHeight = 0;
46 |
47 | // Stateblocks for setting and restoring render states
48 | IDirect3DStateBlock9* m_pStateBlockSaved = nullptr;
49 | IDirect3DStateBlock9* m_pStateBlockDrawText = nullptr;
50 | HRESULT CreateStateBlocks();
51 |
52 | public:
53 | // Constructor / destructor
54 | CD3D9Font();
55 | ~CD3D9Font();
56 |
57 | // Initializing and destroying device-dependent objects
58 | HRESULT InitDeviceObjects(IDirect3DDevice9* pd3dDevice);
59 | void InvalidateDeviceObjects();
60 |
61 | HRESULT CreateFontBitmap(const WCHAR* strFontName, const UINT fontHeight, const UINT fontFlags);
62 |
63 | SIZE GetMaxCharMetric();
64 |
65 | // Function to get extent of text
66 | HRESULT GetTextExtent(const WCHAR* strText, SIZE* pSize);
67 |
68 | // 2D text drawing function
69 | HRESULT Draw2DText(float sx, float sy, const D3DCOLOR color, const WCHAR* strText, const UINT flags=0L);
70 | };
71 |
--------------------------------------------------------------------------------
/Source/D3DUtil/D3D9Geometry.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2019-2020 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | struct POINTVERTEX9 {
24 | DirectX::XMFLOAT4 pos;
25 | DWORD color;
26 | };
27 |
28 | // CD3D9Quadrilateral
29 |
30 | class CD3D9Quadrilateral
31 | {
32 | protected:
33 | IDirect3DDevice9* m_pDevice = nullptr;
34 | IDirect3DVertexBuffer9* m_pVertexBuffer = nullptr;
35 |
36 | bool m_bAlphaBlend = false;
37 | POINTVERTEX9 m_Vertices[6] = {};
38 |
39 | public:
40 | ~CD3D9Quadrilateral();
41 |
42 | HRESULT InitDeviceObjects(IDirect3DDevice9* pDevice);
43 | void InvalidateDeviceObjects();
44 |
45 | HRESULT Set(
46 | const float x1, const float y1,
47 | const float x2, const float y2,
48 | const float x3, const float y3,
49 | const float x4, const float y4,
50 | const D3DCOLOR color);
51 |
52 | HRESULT Draw();
53 | };
54 |
55 | // CD3D9Rectangle
56 |
57 | class CD3D9Rectangle : public CD3D9Quadrilateral
58 | {
59 | private:
60 | using CD3D9Quadrilateral::Set;
61 |
62 | public:
63 | HRESULT Set(const RECT& rect, const D3DCOLOR color);
64 | };
65 |
66 | // CD3D9Stripe
67 |
68 | class CD3D9Stripe : public CD3D9Quadrilateral
69 | {
70 | private:
71 | using CD3D9Quadrilateral::Set;
72 |
73 | public:
74 | HRESULT Set(const int x1, const int y1, const int x2, const int y2, const int thickness, const D3DCOLOR color);
75 | };
76 |
77 | // CD3D9Dots
78 |
79 | class CD3D9Dots
80 | {
81 | protected:
82 | IDirect3DDevice9* m_pDevice = nullptr;
83 | IDirect3DVertexBuffer9* m_pVertexBuffer = nullptr;
84 |
85 | bool m_bAlphaBlend = false;
86 | std::vector m_Vertices;
87 |
88 | virtual inline bool CheckNumPoints(const UINT num)
89 | {
90 | return (num > 0);
91 | }
92 |
93 | virtual inline HRESULT DrawPrimitive()
94 | {
95 | return m_pDevice->DrawPrimitive(D3DPT_POINTLIST, 0, m_Vertices.size());
96 | }
97 |
98 | public:
99 | ~CD3D9Dots();
100 |
101 | HRESULT InitDeviceObjects(IDirect3DDevice9* pDevice);
102 | void InvalidateDeviceObjects();
103 |
104 | void ClearPoints();
105 | bool AddPoints(POINT* poins, const UINT size, const D3DCOLOR color);
106 | bool AddGFPoints(
107 | int Xstart, int Xstep,
108 | int Yaxis, int Yscale,
109 | int* Ydata, UINT Yoffset,
110 | const UINT size, const D3DCOLOR color);
111 |
112 | HRESULT UpdateVertexBuffer();
113 | HRESULT Draw();
114 | };
115 |
116 | // CD3D9Lines
117 |
118 | class CD3D9Lines : public CD3D9Dots
119 | {
120 | private:
121 | using CD3D9Dots::AddGFPoints;
122 |
123 | protected:
124 | inline bool CheckNumPoints(const UINT num) override
125 | {
126 | return (num >= 2 && !(num & 1));
127 | }
128 |
129 | inline HRESULT DrawPrimitive() override
130 | {
131 | return m_pDevice->DrawPrimitive(D3DPT_LINELIST, 0, m_Vertices.size() / 2);
132 | }
133 | };
134 |
135 | // CD3D9Polyline
136 |
137 | class CD3D9Polyline : public CD3D9Dots
138 | {
139 | protected:
140 | inline bool CheckNumPoints(const UINT num) override
141 | {
142 | return (num >= 2 || m_Vertices.size() && num > 0);
143 | }
144 |
145 | inline HRESULT DrawPrimitive() override
146 | {
147 | return m_pDevice->DrawPrimitive(D3DPT_LINESTRIP, 0, m_Vertices.size()-1);
148 | }
149 | };
150 |
--------------------------------------------------------------------------------
/Source/D3DUtil/D3DCommon.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2019 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | // Font creation flags
24 | #define D3DFONT_BOLD 0x0001
25 | #define D3DFONT_ITALIC 0x0002
26 |
27 | struct FloatRect
28 | {
29 | float left;
30 | float top;
31 | float right;
32 | float bottom;
33 | };
34 |
--------------------------------------------------------------------------------
/Source/DX9Helper.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2019-2024 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #include "stdafx.h"
22 | #include
23 | #include "Helper.h"
24 | #include "DX9Helper.h"
25 |
26 | UINT GetAdapter(HWND hWnd, IDirect3D9Ex* pD3D)
27 | {
28 | CheckPointer(hWnd, D3DADAPTER_DEFAULT);
29 | CheckPointer(pD3D, D3DADAPTER_DEFAULT);
30 |
31 | const HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
32 | CheckPointer(hMonitor, D3DADAPTER_DEFAULT);
33 |
34 | const UINT adapterCount = pD3D->GetAdapterCount();
35 | for (UINT adapter = 0; adapter < adapterCount; ++adapter) {
36 | const HMONITOR hAdapterMonitor = pD3D->GetAdapterMonitor(adapter);
37 | if (hAdapterMonitor == hMonitor) {
38 | return adapter;
39 | }
40 | }
41 |
42 | return D3DADAPTER_DEFAULT;
43 | }
44 |
45 | HRESULT Dump4ByteSurface(IDirect3DSurface9* pSurface, const wchar_t* filename)
46 | {
47 | D3DSURFACE_DESC desc;
48 | HRESULT hr = pSurface->GetDesc(&desc);
49 |
50 | if (SUCCEEDED(hr) && (desc.Format == D3DFMT_A8R8G8B8 || desc.Format == D3DFMT_X8R8G8B8 || desc.Format == D3DFMT_AYUV)) {
51 | CComPtr pSurfaceShared;
52 |
53 | if (desc.Pool == D3DPOOL_DEFAULT) {
54 | IDirect3DDevice9* pDevice;
55 | pSurface->GetDevice(&pDevice);
56 | hr = pDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pSurfaceShared, nullptr);
57 | if (SUCCEEDED(hr)) {
58 | hr = pDevice->GetRenderTargetData(pSurface, pSurfaceShared);
59 | }
60 | pDevice->Release();
61 | } else {
62 | pSurfaceShared = pSurface;
63 | }
64 |
65 | if (SUCCEEDED(hr)) {
66 | D3DLOCKED_RECT lr;
67 | hr = pSurfaceShared->LockRect(&lr, nullptr, D3DLOCK_READONLY);
68 |
69 | if (SUCCEEDED(hr)) {
70 | hr = SaveToBMP((BYTE*)lr.pBits, lr.Pitch, desc.Width, desc.Height, 32, filename);
71 | pSurfaceShared->UnlockRect();
72 | }
73 | }
74 |
75 | return hr;
76 | }
77 |
78 | return E_FAIL;
79 | }
80 |
81 | HRESULT DumpDX9Surface(IDirect3DSurface9* pSurface, const wchar_t* filename)
82 | {
83 | CheckPointer(pSurface, E_POINTER);
84 |
85 | HRESULT hr = S_OK;
86 |
87 | D3DSURFACE_DESC desc = {};
88 | hr = pSurface->GetDesc(&desc);
89 | if (FAILED(hr)) {
90 | return hr;
91 | };
92 |
93 | CComPtr pDevice;
94 | hr = pSurface->GetDevice(&pDevice);
95 | if (FAILED(hr)) {
96 | return hr;
97 | };
98 |
99 | CComPtr pTarget;
100 | hr = pDevice->CreateRenderTarget(desc.Width, desc.Height, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pTarget, nullptr);
101 | if (FAILED(hr)) {
102 | return hr;
103 | };
104 |
105 | hr = pDevice->StretchRect(pSurface, nullptr, pTarget, nullptr, D3DTEXF_NONE);
106 | if (FAILED(hr)) {
107 | return hr;
108 | };
109 |
110 | const UINT dib_bitdepth = 32;
111 | const UINT dib_pitch = CalcDibRowPitch(desc.Width, dib_bitdepth);
112 | const UINT dib_size = dib_pitch * desc.Height;
113 |
114 | std::unique_ptr dib(new(std::nothrow) BYTE[sizeof(BITMAPINFOHEADER) + dib_size]);
115 | if (!dib) {
116 | return E_OUTOFMEMORY;
117 | }
118 |
119 | BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)dib.get();
120 | ZeroMemory(bih, sizeof(BITMAPINFOHEADER));
121 | bih->biSize = sizeof(BITMAPINFOHEADER);
122 | bih->biWidth = desc.Width;
123 | bih->biHeight = -(LONG)desc.Height; // top-down RGB bitmap
124 | bih->biBitCount = dib_bitdepth;
125 | bih->biPlanes = 1;
126 | bih->biSizeImage = dib_size;
127 |
128 | D3DLOCKED_RECT r;
129 | hr = pTarget->LockRect(&r, nullptr, D3DLOCK_READONLY);
130 | if (FAILED(hr)) {
131 | return hr;
132 | }
133 |
134 | CopyPlaneAsIs(desc.Height, (BYTE*)(bih + 1), dib_pitch, (BYTE*)r.pBits, r.Pitch);
135 |
136 | pTarget->UnlockRect();
137 |
138 | BITMAPFILEHEADER bfh;
139 | bfh.bfType = 0x4d42;
140 | bfh.bfOffBits = sizeof(bfh) + sizeof(BITMAPINFOHEADER);
141 | bfh.bfSize = bfh.bfOffBits + dib_size;
142 | bfh.bfReserved1 = bfh.bfReserved2 = 0;
143 |
144 | FILE* fp;
145 | if (_wfopen_s(&fp, filename, L"wb") == 0) {
146 | fwrite(&bfh, sizeof(bfh), 1, fp);
147 | fwrite(dib.get(), sizeof(BITMAPINFOHEADER) + dib_size, 1, fp);
148 | fclose(fp);
149 | } else {
150 | hr = E_ACCESSDENIED;
151 | }
152 |
153 | return hr;
154 | }
155 |
--------------------------------------------------------------------------------
/Source/DX9Helper.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2019-2022 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | struct Tex_t
24 | {
25 | CComPtr pTexture;
26 | CComPtr pSurface;
27 | D3DFORMAT Format = D3DFMT_UNKNOWN;
28 | UINT Width = 0;
29 | UINT Height = 0;
30 |
31 |
32 | HRESULT CheckCreate(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const UINT width, const UINT height, DWORD usage) {
33 | if (format == Format && width == Width && height == Height) {
34 | return S_OK;
35 | }
36 |
37 | return Create(pDevice, format, width, height, usage);
38 | }
39 |
40 | HRESULT Create(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const UINT width, const UINT height, DWORD usage) {
41 | Release();
42 |
43 | HRESULT hr = pDevice->CreateTexture(width, height, 1, usage, format, D3DPOOL_DEFAULT, &pTexture, nullptr);
44 | if (S_OK == hr) {
45 | hr = pTexture->GetSurfaceLevel(0, &pSurface);
46 | if (S_OK == hr) {
47 | D3DSURFACE_DESC desc = {};
48 | EXECUTE_ASSERT(S_OK == pSurface->GetDesc(&desc));
49 | Format = desc.Format;
50 | Width = desc.Width;
51 | Height = desc.Height;
52 | } else {
53 | ASSERT(FALSE);
54 | pTexture.Release();
55 | }
56 | }
57 |
58 | return hr;
59 | }
60 |
61 | virtual void Release() {
62 | pSurface.Release();
63 | pTexture.Release();
64 | Format = D3DFMT_UNKNOWN;
65 | Width = 0;
66 | Height = 0;
67 | }
68 | };
69 |
70 | struct Tex9Video_t : Tex_t
71 | {
72 | Tex_t Plane2;
73 | Tex_t Plane3;
74 |
75 | HRESULT CreateEx(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const DX9PlaneConfig* pPlanes, UINT width, const UINT height, DWORD usage) {
76 | Release();
77 |
78 | HRESULT hr;
79 |
80 | if (pPlanes) {
81 | if (format == D3DFMT_YUY2) {
82 | width /= 2;
83 | }
84 | hr = Create(pDevice, pPlanes->FmtPlane1, width, height, usage);
85 |
86 | if (S_OK == hr && pPlanes->FmtPlane2) {
87 | const UINT chromaWidth = width / pPlanes->div_chroma_w;
88 | const UINT chromaHeight = height / pPlanes->div_chroma_h;
89 | hr = Plane2.Create(pDevice, pPlanes->FmtPlane2, chromaWidth, chromaHeight, usage);
90 |
91 | if (S_OK == hr && pPlanes->FmtPlane3) {
92 | hr = Plane3.Create(pDevice, pPlanes->FmtPlane3, chromaWidth, chromaHeight, usage);
93 | }
94 | }
95 | }
96 | else {
97 | hr = Create(pDevice, format, width, height, usage);
98 | }
99 |
100 | if (FAILED(hr)) {
101 | Release();
102 | }
103 |
104 | return hr;
105 | }
106 |
107 | void Release() override {
108 | Plane3.Release();
109 | Plane2.Release();
110 | Tex_t::Release();
111 | }
112 | };
113 |
114 | class CTexRing
115 | {
116 | Tex_t Texs[2];
117 | int index = 0;
118 | UINT size = 0;
119 |
120 | public:
121 | HRESULT CheckCreate(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const UINT width, const UINT height, const UINT num) {
122 | HRESULT hr = S_FALSE;
123 | if (num == 0) {
124 | Release();
125 | return hr;
126 | }
127 |
128 | index = 0;
129 | size = 0;
130 | hr = Texs[0].CheckCreate(pDevice, format, width, height, D3DUSAGE_RENDERTARGET);
131 | size++;
132 | if (S_OK == hr && num >= 2) {
133 | hr = Texs[1].CheckCreate(pDevice, format, width, height, D3DUSAGE_RENDERTARGET);
134 | size++;
135 | } else {
136 | Texs[1].Release();
137 | }
138 | return hr;
139 | }
140 |
141 | HRESULT Create(IDirect3DDevice9Ex* pDevice, const D3DFORMAT format, const UINT width, const UINT height, const UINT num) {
142 | Release();
143 | HRESULT hr = S_FALSE;
144 | if (num >= 1) {
145 | hr = Texs[0].Create(pDevice, format, width, height, D3DUSAGE_RENDERTARGET);
146 | size++;
147 | if (S_OK == hr && num >= 2) {
148 | hr = Texs[1].Create(pDevice, format, width, height, D3DUSAGE_RENDERTARGET);
149 | size++;
150 | }
151 | }
152 | return hr;
153 | }
154 |
155 | UINT Size() {
156 | return size;
157 | }
158 |
159 | void Release() {
160 | Texs[0].Release();
161 | Texs[1].Release();
162 | index = 0;
163 | size = 0;
164 | }
165 |
166 | Tex_t* GetFirstTex() {
167 | index = 0;
168 | return &Texs[0];
169 | }
170 |
171 | Tex_t* GetNextTex() {
172 | index = (index + 1) & 1;
173 | return &Texs[index];
174 | }
175 | };
176 |
177 | struct ExternalPixelShader9_t
178 | {
179 | std::wstring name;
180 | CComPtr shader;
181 | };
182 |
183 | UINT GetAdapter(HWND hWnd, IDirect3D9Ex* pD3D);
184 |
185 | HRESULT Dump4ByteSurface(IDirect3DSurface9* pSurface, const wchar_t* filename);
186 |
187 | HRESULT DumpDX9Surface(IDirect3DSurface9* pSurface, const wchar_t* filename);
188 |
--------------------------------------------------------------------------------
/Source/DisplayConfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2020-2025 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | #include
24 |
25 | #if !defined(NTDDI_WIN11_GE)
26 | enum {
27 | DISPLAYCONFIG_DEVICE_INFO_SET_RESERVED1 = 14,
28 | DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 = 15,
29 | DISPLAYCONFIG_DEVICE_INFO_SET_HDR_STATE = 16,
30 | DISPLAYCONFIG_DEVICE_INFO_SET_WCG_STATE = 17,
31 | };
32 | #endif
33 |
34 | #if !defined(NTDDI_WIN11_GA) || (NTDDI_VERSION < NTDDI_WIN11_GA)
35 | typedef enum _DISPLAYCONFIG_ADVANCED_COLOR_MODE {
36 | DISPLAYCONFIG_ADVANCED_COLOR_MODE_SDR,
37 | DISPLAYCONFIG_ADVANCED_COLOR_MODE_WCG,
38 | DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR
39 | } DISPLAYCONFIG_ADVANCED_COLOR_MODE;
40 |
41 | typedef struct _DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 {
42 | DISPLAYCONFIG_DEVICE_INFO_HEADER header;
43 | union {
44 | struct {
45 | UINT32 advancedColorSupported : 1;
46 | UINT32 advancedColorActive : 1;
47 | UINT32 reserved1 : 1;
48 | UINT32 advancedColorLimitedByPolicy : 1;
49 | UINT32 highDynamicRangeSupported : 1;
50 | UINT32 highDynamicRangeUserEnabled : 1;
51 | UINT32 wideColorSupported : 1;
52 | UINT32 wideColorUserEnabled : 1;
53 | UINT32 reserved : 24;
54 | };
55 | UINT32 value;
56 | };
57 | DISPLAYCONFIG_COLOR_ENCODING colorEncoding;
58 | UINT32 bitsPerColorChannel;
59 | DISPLAYCONFIG_ADVANCED_COLOR_MODE activeColorMode;
60 | } DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2;
61 |
62 | typedef struct _DISPLAYCONFIG_SET_HDR_STATE {
63 | DISPLAYCONFIG_DEVICE_INFO_HEADER header;
64 | union {
65 | struct {
66 | UINT32 enableHdr : 1;
67 | UINT32 reserved : 31;
68 | };
69 | UINT32 value;
70 | };
71 | } DISPLAYCONFIG_SET_HDR_STATE;
72 | #endif
73 |
74 | struct DisplayConfig_t {
75 | union {
76 | struct {
77 | UINT32 advancedColorSupported : 1; // A type of advanced color is supported
78 | UINT32 advancedColorEnabled : 1; // A type of advanced color is enabled
79 | UINT32 wideColorEnforced : 1; // Wide color gamut is enabled
80 | UINT32 advancedColorForceDisabled : 1; // Advanced color is force disabled due to system/OS policy
81 | UINT32 reserved : 28;
82 | };
83 | UINT32 value;
84 | } advancedColor;
85 |
86 | struct {
87 | union {
88 | struct {
89 | UINT32 advancedColorSupported : 1;
90 | UINT32 advancedColorActive : 1;
91 | UINT32 reserved1 : 1;
92 | UINT32 advancedColorLimitedByPolicy : 1;
93 | UINT32 highDynamicRangeSupported : 1;
94 | UINT32 highDynamicRangeUserEnabled : 1;
95 | UINT32 wideColorSupported : 1;
96 | UINT32 wideColorUserEnabled : 1;
97 | UINT32 reserved : 24;
98 | };
99 | UINT32 value;
100 | };
101 |
102 | DISPLAYCONFIG_ADVANCED_COLOR_MODE activeColorMode;
103 | } windows1124H2Colors;
104 |
105 | UINT32 width;
106 | UINT32 height;
107 | UINT32 bitsPerChannel;
108 | DISPLAYCONFIG_COLOR_ENCODING colorEncoding;
109 | DISPLAYCONFIG_RATIONAL refreshRate;
110 | DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
111 | DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
112 | WCHAR displayName[CCHDEVICENAME];
113 | WCHAR monitorName[64];
114 | DISPLAYCONFIG_MODE_INFO modeTarget;
115 |
116 | bool HDRSupported() const {
117 | if (IsWindows11_24H2OrGreater()) {
118 | return windows1124H2Colors.highDynamicRangeSupported;
119 | }
120 |
121 | return advancedColor.advancedColorSupported && !advancedColor.wideColorEnforced && !advancedColor.advancedColorForceDisabled;
122 | }
123 | bool HDREnabled() const {
124 | if (IsWindows11_24H2OrGreater()) {
125 | return windows1124H2Colors.highDynamicRangeSupported && windows1124H2Colors.activeColorMode == DISPLAYCONFIG_ADVANCED_COLOR_MODE::DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR;
126 | }
127 |
128 | return advancedColor.advancedColorEnabled && !advancedColor.wideColorEnforced && !advancedColor.advancedColorForceDisabled;
129 | }
130 | bool ACMEnabled() const {
131 | if (IsWindows11_24H2OrGreater()) {
132 | return windows1124H2Colors.wideColorSupported && windows1124H2Colors.wideColorUserEnabled;
133 | }
134 |
135 | return false;
136 | }
137 | };
138 |
139 | double GetRefreshRate(const wchar_t* displayName);
140 |
141 | bool GetDisplayConfig(const wchar_t* displayName, DisplayConfig_t& displayConfig);
142 |
143 | bool GetDisplayConfigs(std::vector& displayConfigs);
144 |
145 | const wchar_t* ColorEncodingToString(DISPLAYCONFIG_COLOR_ENCODING colorEncoding);
146 | const wchar_t* OutputTechnologyToString(DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology);
147 |
148 | std::wstring DisplayConfigToString(const DisplayConfig_t& dc);
149 |
150 | std::wstring D3DDisplayModeToString(const D3DDISPLAYMODEEX& dm);
151 |
--------------------------------------------------------------------------------
/Source/IVideoRenderer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2018-2024 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | #include
24 |
25 | enum :int {
26 | TEXFMT_AUTOINT = 0,
27 | TEXFMT_8INT = 8,
28 | TEXFMT_10INT = 10,
29 | TEXFMT_16FLOAT = 16,
30 | };
31 |
32 | enum :int {
33 | SUPERRES_Disable = 0,
34 | SUPERRES_SD,
35 | SUPERRES_720p,
36 | SUPERRES_1080p,
37 | SUPERRES_1440p,
38 | SUPERRES_COUNT
39 | };
40 |
41 | enum :int {
42 | CHROMA_Nearest = 0,
43 | CHROMA_Bilinear,
44 | CHROMA_CatmullRom,
45 | CHROMA_COUNT
46 | };
47 |
48 | enum :int {
49 | UPSCALE_Nearest = 0,
50 | UPSCALE_Mitchell,
51 | UPSCALE_CatmullRom,
52 | UPSCALE_Lanczos2,
53 | UPSCALE_Lanczos3,
54 | UPSCALE_Jinc2,
55 | UPSCALE_COUNT
56 | };
57 |
58 | enum :int {
59 | DOWNSCALE_Box = 0,
60 | DOWNSCALE_Bilinear,
61 | DOWNSCALE_Hamming,
62 | DOWNSCALE_Bicubic,
63 | DOWNSCALE_BicubicSharp,
64 | DOWNSCALE_Lanczos,
65 | DOWNSCALE_COUNT
66 | };
67 |
68 | enum :int {
69 | SWAPEFFECT_Discard = 0,
70 | SWAPEFFECT_Flip,
71 | SWAPEFFECT_COUNT
72 | };
73 |
74 | enum :int {
75 | HDRTD_Disabled = 0,
76 | HDRTD_On_Fullscreen,
77 | HDRTD_On,
78 | HDRTD_OnOff_Fullscreen,
79 | HDRTD_OnOff
80 | };
81 |
82 | #define SDR_NITS_DEF 125
83 | #define SDR_NITS_MIN 25
84 | #define SDR_NITS_MAX 400
85 | #define SDR_NITS_STEP 5
86 |
87 | struct VPEnableFormats_t {
88 | bool bNV12;
89 | bool bP01x;
90 | bool bYUY2;
91 | bool bOther;
92 | };
93 |
94 | struct Settings_t {
95 | bool bUseD3D11;
96 | bool bShowStats;
97 | int iResizeStats;
98 | int iTexFormat;
99 | VPEnableFormats_t VPFmts;
100 | bool bDeintDouble;
101 | bool bVPScaling;
102 | int iVPSuperRes;
103 | bool bVPRTXVideoHDR;
104 | int iChromaScaling;
105 | int iUpscaling;
106 | int iDownscaling;
107 | bool bInterpolateAt50pct;
108 | bool bUseDither;
109 | bool bDeintBlend;
110 | int iSwapEffect;
111 | bool bExclusiveFS;
112 | bool bVBlankBeforePresent;
113 | bool bAdjustPresentTime;
114 | bool bReinitByDisplay;
115 | bool bHdrPreferDoVi;
116 | bool bHdrPassthrough;
117 | int iHdrToggleDisplay;
118 | int iHdrOsdBrightness;
119 | bool bConvertToSdr;
120 | int iSDRDisplayNits;
121 |
122 | Settings_t() {
123 | SetDefault();
124 | }
125 |
126 | void SetDefault() {
127 | if (IsWindows8OrGreater()) {
128 | bUseD3D11 = true;
129 | } else {
130 | bUseD3D11 = false;
131 | }
132 | bShowStats = false;
133 | iResizeStats = 0;
134 | iTexFormat = TEXFMT_AUTOINT;
135 | VPFmts.bNV12 = true;
136 | VPFmts.bP01x = true;
137 | VPFmts.bYUY2 = true;
138 | VPFmts.bOther = true;
139 | bDeintDouble = true;
140 | bVPScaling = true;
141 | iVPSuperRes = SUPERRES_Disable;
142 | bVPRTXVideoHDR = false;
143 | iChromaScaling = CHROMA_Bilinear;
144 | iUpscaling = UPSCALE_CatmullRom;
145 | iDownscaling = DOWNSCALE_Hamming;
146 | bInterpolateAt50pct = true;
147 | bUseDither = true;
148 | bDeintBlend = false;
149 | iSwapEffect = SWAPEFFECT_Flip;
150 | bExclusiveFS = false;
151 | bVBlankBeforePresent = false;
152 | bAdjustPresentTime = true;
153 | bReinitByDisplay = false;
154 | bHdrPreferDoVi = false;
155 | if (IsWindows10OrGreater()) {
156 | bHdrPassthrough = true;
157 | } else {
158 | bHdrPassthrough = false;
159 | }
160 | iHdrToggleDisplay = HDRTD_Disabled;
161 | bConvertToSdr = true;
162 | iHdrOsdBrightness = 0;
163 | iSDRDisplayNits = SDR_NITS_DEF;
164 | }
165 | };
166 |
167 | interface __declspec(uuid("1AB00F10-5F55-42AC-B53F-38649F11BE3E"))
168 | IVideoRenderer : public IUnknown {
169 | STDMETHOD(GetVideoProcessorInfo) (std::wstring& str) PURE;
170 | STDMETHOD_(bool, GetActive()) PURE;
171 |
172 | STDMETHOD_(void, GetSettings(Settings_t& setings)) PURE;
173 | STDMETHOD_(void, SetSettings(const Settings_t& setings)) PURE;
174 |
175 | STDMETHOD(SaveSettings()) PURE;
176 | };
177 |
--------------------------------------------------------------------------------
/Source/MediaSampleSideData.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010-2017 Hendrik Leppkes
3 | * http://www.1f0.de
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 2 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License along
16 | * with this program; if not, write to the Free Software Foundation, Inc.,
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | */
19 |
20 | #include "stdafx.h"
21 | #include "MediaSampleSideData.h"
22 |
23 | CMediaSampleSideData::CMediaSampleSideData(LPCTSTR pName, CBaseAllocator *pAllocator, HRESULT *phr, LPBYTE pBuffer, LONG length)
24 | : CMediaSample(pName, pAllocator, phr, pBuffer, length)
25 | {
26 | }
27 |
28 | CMediaSampleSideData::~CMediaSampleSideData()
29 | {
30 | ReleaseSideData();
31 | }
32 |
33 | STDMETHODIMP CMediaSampleSideData::QueryInterface(REFIID riid, __deref_out void **ppv)
34 | {
35 | CheckPointer(ppv, E_POINTER);
36 | ValidateReadWritePtr(ppv, sizeof(PVOID));
37 |
38 | if (riid == __uuidof(IMediaSideData)) {
39 | return GetInterface((IMediaSideData*) this, ppv);
40 | }
41 | else {
42 | return __super::QueryInterface(riid, ppv);
43 | }
44 | }
45 |
46 | STDMETHODIMP_(ULONG) CMediaSampleSideData::Release()
47 | {
48 | /* Decrement our own private reference count */
49 | LONG lRef;
50 | if (m_cRef == 1) {
51 | lRef = 0;
52 | m_cRef = 0;
53 | }
54 | else {
55 | lRef = InterlockedDecrement(&m_cRef);
56 | }
57 | ASSERT(lRef >= 0);
58 |
59 | /* Did we release our final reference count */
60 | if (lRef == 0) {
61 | /* Free all resources */
62 | if (m_dwFlags & Sample_TypeChanged) {
63 | SetMediaType(NULL);
64 | }
65 | ASSERT(m_pMediaType == NULL);
66 | m_dwFlags = 0;
67 | m_dwTypeSpecificFlags = 0;
68 | m_dwStreamId = AM_STREAM_MEDIA;
69 |
70 | ReleaseSideData();
71 |
72 | /* This may cause us to be deleted */
73 | // Our refcount is reliably 0 thus no-one will mess with us
74 | m_pAllocator->ReleaseBuffer(this);
75 | }
76 | return (ULONG)lRef;
77 | }
78 |
79 | void CMediaSampleSideData::ReleaseSideData()
80 | {
81 | CAutoLock Lock(&m_csSideData);
82 |
83 | for (auto& [guid, sd] : m_SideData) {
84 | _aligned_free(sd.pData);
85 | }
86 |
87 | m_SideData.clear();
88 | }
89 |
90 | // IMediaSideData
91 | STDMETHODIMP CMediaSampleSideData::SetSideData(GUID guidType, const BYTE *pData, size_t size)
92 | {
93 | if (!pData || !size)
94 | return E_POINTER;
95 |
96 | CAutoLock Lock(&m_csSideData);
97 |
98 | auto it = m_SideData.find(guidType);
99 | if (it != m_SideData.end())
100 | {
101 | SideDataEntry *sd = &(it->second);
102 | BYTE *newData = (BYTE *)_aligned_realloc(sd->pData, size, 16);
103 | if (newData) {
104 | sd->size = size;
105 | sd->pData = newData;
106 | memcpy(newData, pData, size);
107 | }
108 | else
109 | {
110 | return E_OUTOFMEMORY;
111 | }
112 | }
113 | else
114 | {
115 | SideDataEntry sd;
116 | sd.pData = (BYTE *)_aligned_malloc(size, 16);
117 | if (sd.pData) {
118 | sd.size = size;
119 | memcpy(sd.pData, pData, size);
120 | }
121 | else
122 | {
123 | return E_OUTOFMEMORY;
124 | }
125 |
126 | m_SideData[guidType] = sd;
127 | }
128 |
129 | return S_OK;
130 | }
131 |
132 | STDMETHODIMP CMediaSampleSideData::GetSideData(GUID guidType, const BYTE **pData, size_t *pSize)
133 | {
134 | if (!pData || !pSize)
135 | return E_POINTER;
136 |
137 | CAutoLock Lock(&m_csSideData);
138 |
139 | auto it = m_SideData.find(guidType);
140 | if (it != m_SideData.end())
141 | {
142 | *pData = it->second.pData;
143 | *pSize = it->second.size;
144 |
145 | return S_OK;
146 | }
147 |
148 | return E_FAIL;
149 | }
150 |
--------------------------------------------------------------------------------
/Source/MediaSampleSideData.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010-2017 Hendrik Leppkes
3 | * http://www.1f0.de
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 2 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License along
16 | * with this program; if not, write to the Free Software Foundation, Inc.,
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 | */
19 |
20 | #pragma once
21 |
22 | #include "../Include/IMediaSideData.h"
23 | #include