├── .clang-format
├── .gitattributes
├── .github
└── workflows
│ └── msbuild.yml
├── .gitignore
├── .gitmodules
├── Anime4KCPPCore.vcxproj
├── Anime4KCPPCore.vcxproj.filters
├── Dlls
└── Dlls.csproj
├── HttpDownload
├── HttpDownload.cpp
├── HttpDownload.vcxproj
├── HttpDownload.vcxproj.filters
├── ReadMe.txt
├── stdafx.cpp
├── stdafx.h
└── targetver.h
├── LICENSE
├── Player.sln
├── Player
├── AsyncGetUrlUnderMouseCursor.cpp
├── AsyncGetUrlUnderMouseCursor.h
├── ByteStreamBuffer.h
├── D3DFONT.CPP
├── D3DFONT.H
├── DialogBarPlayerControl.cpp
├── DialogBarPlayerControl.h
├── DialogBarRange.cpp
├── DialogBarRange.h
├── DialogOpenURL.cpp
├── DialogOpenURL.h
├── EditTime.cpp
├── EditTime.h
├── FrameToHglobal.cpp
├── FrameToHglobal.h
├── GetClipboardText.h
├── HandleFilesSequence.cpp
├── HandleFilesSequence.h
├── I420Effect.cpp
├── I420Effect.h
├── I420Effect_PS.hlsl
├── IEraseableArea.h
├── ImageUpscale.cpp
├── ImageUpscale.h
├── MainFrm.cpp
├── MainFrm.h
├── MakeDelegate.h
├── MemoryMappedFile.h
├── OpenSubtitlesFile.cpp
├── OpenSubtitlesFile.h
├── Player.cpp
├── Player.h
├── Player.rc
├── Player.vcxproj
├── Player.vcxproj.filters
├── PlayerDoc.cpp
├── PlayerDoc.h
├── PlayerView.cpp
├── PlayerView.h
├── PlayerViewD2D.cpp
├── PlayerViewD2D.h
├── ReadMe.txt
├── SecondsToString.h
├── StringDifference.cpp
├── StringDifference.h
├── YouTuber.cpp
├── YouTuber.h
├── res
│ ├── Player.ico
│ ├── Player.rc2
│ ├── PlayerDoc.ico
│ ├── Toolbar.bmp
│ ├── audio.ico
│ ├── audio_off.ico
│ ├── full_screen.ico
│ ├── launch.mkv
│ ├── pause.ico
│ └── play.ico
├── resource.h
├── stdafx.cpp
├── stdafx.h
├── targetver.h
└── update_version.cmd
├── QtPlayer
├── .gitattributes
├── .gitignore
├── CMakeLists.txt
├── customdockwidget.cpp
├── customdockwidget.h
├── ffmpegdecoder.cpp
├── ffmpegdecoder.h
├── main.cpp
├── mainwindow.cpp
├── mainwindow.h
├── mainwindow.ui
├── mousehoverbutton.cpp
├── mousehoverbutton.h
├── opengldisplay.cpp
├── opengldisplay.h
├── portaudioplayer.cpp
├── portaudioplayer.h
├── resources
│ ├── images
│ │ ├── control
│ │ │ ├── icodelete.png
│ │ │ ├── icoplay.png
│ │ │ ├── player___btn_globe___click___(31x31).png
│ │ │ ├── player___btn_globe___default___(31x31).png
│ │ │ ├── player___btn_globe___hover___(31x31).png
│ │ │ ├── player___btn_pause___clicked___(40x31).png
│ │ │ ├── player___btn_pause___default___(40x31).png
│ │ │ ├── player___btn_pause___hover___(40x31).png
│ │ │ ├── player___btn_play___clicked___(40x31).png
│ │ │ ├── player___btn_play___default___(40x31).png
│ │ │ ├── player___btn_play___hover___(40x31).png
│ │ │ ├── player___btn_sound_off___clicked___(31x31).png
│ │ │ ├── player___btn_sound_off___default___(31x31).png
│ │ │ ├── player___btn_sound_off___hover___(31x31).png
│ │ │ ├── player___btn_sound_on___clicked___(31x31).png
│ │ │ ├── player___btn_sound_on___default___(31x31).png
│ │ │ ├── player___btn_sound_on___hover___(31x31).png
│ │ │ ├── player___btn_stop___clicked___(31x31).png
│ │ │ ├── player___btn_stop___default___(31x31).png
│ │ │ ├── player___btn_stop___hover___(31x31).png
│ │ │ ├── player_bg___(230x41).png
│ │ │ └── player_bg_fs___(230x41).png
│ │ ├── help41.png
│ │ ├── play_transparent.png
│ │ ├── spinner.gif
│ │ ├── style
│ │ │ ├── box-shadow.png
│ │ │ ├── busy.png
│ │ │ ├── button-blank.png
│ │ │ ├── button_disable.png
│ │ │ ├── button_down.png
│ │ │ ├── button_hover.png
│ │ │ ├── button_normal.png
│ │ │ ├── circle-shadow.png
│ │ │ ├── down_arrow.png
│ │ │ ├── down_arrow_grey.png
│ │ │ ├── floatpanel.png
│ │ │ ├── header_arrow_down.png
│ │ │ ├── header_line.png
│ │ │ ├── lineedit.png
│ │ │ ├── progress_dropdown.png
│ │ │ ├── scroll-button-down-hover.png
│ │ │ ├── scroll-button-down.png
│ │ │ ├── scroll-button-left-hover.png
│ │ │ ├── scroll-button-left.png
│ │ │ ├── scroll-button-right-hover.png
│ │ │ ├── scroll-button-right.png
│ │ │ ├── scroll-button-up-hover.png
│ │ │ ├── scroll-button-up.png
│ │ │ ├── scroll-hhandle-hover.png
│ │ │ ├── scroll-hhandle.png
│ │ │ ├── scroll-vhandle-hover.png
│ │ │ ├── scroll-vhandle.png
│ │ │ └── tooltip-background.png
│ │ ├── triangle_down.png
│ │ ├── triangle_right.png
│ │ ├── video___btn_play___clicked___(94x94).png
│ │ ├── video___btn_play___default___(94x94).png
│ │ ├── video___btn_play___hover___(94x94).png
│ │ └── video_seek_cursor.png
│ ├── qt.conf
│ ├── resources.qrc
│ ├── style.css
│ ├── win7.manifest
│ └── winres.rc.in
├── videocontrol.cpp
├── videocontrol.h
├── videocontrol.ui
├── videodisplay.cpp
├── videodisplay.h
├── videoplayer.cpp
├── videoplayer.h
├── videoplayerwidget.cpp
├── videoplayerwidget.h
├── videoprogressbar.cpp
├── videoprogressbar.h
├── videowidget.cpp
├── videowidget.h
├── volumeprogressbar.cpp
├── volumeprogressbar.h
├── widgetdisplay.cpp
└── widgetdisplay.h
├── README.md
├── Setup
├── Setup.vdproj
└── python-embed-win32.7z
├── ThirdParty
└── include
│ ├── cmdline
│ └── cmdline.hpp
│ ├── ini17
│ └── ini17.hpp
│ └── opencl
│ └── CL
│ └── opencl.hpp
├── ToUTF8
├── ToUTF8.cpp
├── ToUTF8.vcxproj
└── ToUTF8.vcxproj.filters
├── audio
├── AudioPitchDecorator.cpp
├── AudioPitchDecorator.h
├── AudioPlayerImpl.cpp
├── AudioPlayerImpl.h
├── AudioPlayerWasapi.cpp
├── AudioPlayerWasapi.h
├── ReadMe.txt
├── audio.vcxproj
├── audio.vcxproj.filters
├── smbPitchShift.cpp
└── smbPitchShift.h
├── core
└── ac_export.h
├── edit_git_subst_cfg.cmd
├── ffmpeg-3.3.3-experimental-patch
├── common.before.h
├── common.h
├── hevcdsp_template.before.c
└── hevcdsp_template.c
├── ffmpeg-4.3.2-experimental-patch
├── common.before.h
├── common.h
├── hevcdsp_template.before.c
└── hevcdsp_template.c
├── networking
├── ReadMe.txt
├── crypt.h
├── http_download.cpp
├── http_download.h
├── http_get.cpp
├── http_get.h
├── httpioapi.cpp
├── httprequest_h.h
├── httprequest_i.c
├── ioapi.h
├── networking.vcxproj
├── networking.vcxproj.filters
├── unzip.c
└── unzip.h
├── remove_pytube.cmd
├── remove_youtube_transcript_api.cmd
└── video
├── audioparserunnable.cpp
├── audioplayer.h
├── decoderinterface.h
├── decoderiocontext.cpp
├── decoderiocontext.h
├── displayrunnable.cpp
├── ffmpeg_dxva2.cpp
├── ffmpeg_dxva2.h
├── ffmpegdecoder.cpp
├── ffmpegdecoder.h
├── fqueue.h
├── interlockedadd.h
├── makeguard.h
├── parserunnable.cpp
├── subtitles.cpp
├── subtitles.h
├── video.vcxproj
├── video.vcxproj.filters
├── videoframe.h
├── videoparserunnable.cpp
└── vqueue.h
/.clang-format:
--------------------------------------------------------------------------------
1 | BasedOnStyle: Google
2 | UseTab: Never
3 | IndentWidth: 4
4 | BreakBeforeBraces: Allman
5 | AllowShortIfStatementsOnASingleLine: false
6 | IndentCaseLabels: false
7 | ColumnLimit: 99
8 | IndentAccessModifiers: false
9 | AccessModifierOffset: -4
10 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.github/workflows/msbuild.yml:
--------------------------------------------------------------------------------
1 | # This workflow uses actions that are not certified by GitHub.
2 | # They are provided by a third-party and are governed by
3 | # separate terms of service, privacy policy, and support
4 | # documentation.
5 |
6 | name: MSBuild
7 |
8 | on:
9 | workflow_dispatch:
10 |
11 | env:
12 | # Path to the solution file relative to the root of the project.
13 | SOLUTION_FILE_PATH: ./Player.sln
14 |
15 | # Configuration type to build.
16 | # You can convert this to a build matrix if you need coverage of multiple configuration types.
17 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
18 | BUILD_CONFIGURATION: Release
19 | # https://learn.microsoft.com/en-us/vcpkg/consume/binary-caching-github-actions-cache?source=recommendations
20 | VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
21 |
22 |
23 | jobs:
24 | build:
25 | runs-on: windows-latest
26 |
27 | strategy:
28 | matrix:
29 | platform: [x86, x64]
30 |
31 | steps:
32 | - uses: actions/checkout@v4
33 | with:
34 | submodules: true # Ensure submodules are checked out
35 |
36 | - name: Create Directory.Build.props
37 | run: |
38 | $content = "10.0.22621.0v4.6.2v143"
39 | $filePath = "./Directory.Build.props"
40 | Set-Content -Path $filePath -Value $content
41 |
42 | - name: Add MSBuild to PATH
43 | id: setup-msbuild
44 | uses: microsoft/setup-msbuild@v2
45 |
46 | - name: Export GitHub Actions cache environment variables
47 | uses: actions/github-script@v7
48 | with:
49 | script: |
50 | core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
51 | core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
52 |
53 | # see https://github.com/microsoft/vcpkg/issues/43802
54 | - name: Install vcpkg
55 | run: |
56 | git clone https://github.com/microsoft/vcpkg.git
57 | cd vcpkg
58 | git checkout 62aa44929954469878eb8fc562af706a8f5615a5
59 | ./bootstrap-vcpkg.bat
60 | ./vcpkg integrate install
61 |
62 | - name: Install dependencies
63 | run: ./vcpkg/vcpkg install boost boost-log dtl ffmpeg[ffmpeg,x264,nonfree,gpl,vpx,webp,zlib,xml2] opencv4 python3 boost-python opencl --triplet=${{matrix.platform}}-windows
64 |
65 | - name: Restore NuGet packages
66 | working-directory: ${{env.GITHUB_WORKSPACE}}
67 | run: nuget restore ${{env.SOLUTION_FILE_PATH}}
68 |
69 | - name: Find OpenCV Header
70 | run: |
71 | $opencvHeader = Get-ChildItem -Path "./vcpkg/" -Recurse -Filter "opencv.hpp" | Where-Object { $_.FullName -match "opencv2\\opencv.hpp" }
72 | if ($opencvHeader) {
73 | Write-Output "Found OpenCV header at: $($opencvHeader.FullName)"
74 | } else {
75 | Write-Error "OpenCV header not found"
76 | }
77 |
78 | - name: Build
79 | working-directory: ${{env.GITHUB_WORKSPACE}}
80 | # Add additional options to the MSBuild command line here (like platform or verbosity level).
81 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
82 | run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} /p:Platform=${{matrix.platform == 'x86' && 'Win32' || matrix.platform}} /t:Player:Rebuild ${{env.SOLUTION_FILE_PATH}}
83 |
84 | - name: Complete build artifacts
85 | run: |
86 | $CRT_path = Get-ChildItem -Path "${{ steps.setup-msbuild.outputs.msbuildPath }}/../../../VC/Redist/MSVC/*/${{matrix.platform}}/Microsoft.VC143.CRT" | Select-Object -First 1 -ExpandProperty FullName
87 | $MFC_path = Get-ChildItem -Path "${{ steps.setup-msbuild.outputs.msbuildPath }}/../../../VC/Redist/MSVC/*/${{matrix.platform}}/Microsoft.VC143.MFC" | Select-Object -First 1 -ExpandProperty FullName
88 | Write-Output "CRT PATH=$CRT_path"
89 | Write-Output "MFC PATH=$MFC_path"
90 | ./vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary "./${{matrix.platform == 'x64' && matrix.platform || ''}}/Release/Player.exe" -installedDir "$CRT_path" -OutVariable out
91 | ./vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary "./${{matrix.platform == 'x64' && matrix.platform || ''}}/Release/Player.exe" -installedDir "$MFC_path" -OutVariable out
92 |
93 | - name: Copy FFmpeg tools
94 | run: Copy-Item -Path "./vcpkg/installed/${{matrix.platform}}-windows/tools/ffmpeg/*" -Destination "./${{matrix.platform == 'x64' && matrix.platform || ''}}/Release/" -Recurse -Force -ErrorAction SilentlyContinue
95 |
96 | - name: Delete .pdb files
97 | run: Remove-Item -Path "./${{matrix.platform == 'x64' && matrix.platform || ''}}/Release/*.pdb" -Force
98 |
99 | - name: Delete .lib files
100 | run: Remove-Item -Path "./${{matrix.platform == 'x64' && matrix.platform || ''}}/Release/*.lib" -Force
101 |
102 | - name: Upload build artifacts
103 | uses: actions/upload-artifact@v4
104 | with:
105 | name: build-artifacts-${{matrix.platform}}
106 | path: ./${{matrix.platform == 'x64' && matrix.platform || ''}}/Release
107 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 | *.publishproj
131 |
132 | # NuGet Packages Directory
133 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
134 | #packages/
135 |
136 | # Windows Azure Build Output
137 | csx
138 | *.build.csdef
139 |
140 | # Windows Store app package directory
141 | AppPackages/
142 |
143 | # Others
144 | sql/
145 | *.Cache
146 | ClientBin/
147 | [Ss]tyle[Cc]op.*
148 | ~$*
149 | *~
150 | *.dbmdl
151 | *.[Pp]ublish.xml
152 | *.pfx
153 | *.publishsettings
154 |
155 | # RIA/Silverlight projects
156 | Generated_Code/
157 |
158 | # Backup & report files from converting an old project file to a newer
159 | # Visual Studio version. Backup files are not needed, because we have git ;-)
160 | _UpgradeReport_Files/
161 | Backup*/
162 | UpgradeLog*.XML
163 | UpgradeLog*.htm
164 |
165 | # SQL Server files
166 | App_Data/*.mdf
167 | App_Data/*.ldf
168 |
169 | #############
170 | ## Windows detritus
171 | #############
172 |
173 | # Windows image file caches
174 | Thumbs.db
175 | ehthumbs.db
176 |
177 | # Folder config file
178 | Desktop.ini
179 |
180 | # Recycle Bin used on file shares
181 | $RECYCLE.BIN/
182 |
183 | # Mac crap
184 | .DS_Store
185 |
186 |
187 | #############
188 | ## Python
189 | #############
190 |
191 | *.py[cod]
192 |
193 | # Packages
194 | *.egg
195 | *.egg-info
196 | dist/
197 | build/
198 | eggs/
199 | parts/
200 | var/
201 | sdist/
202 | develop-eggs/
203 | .installed.cfg
204 |
205 | # Installer logs
206 | pip-log.txt
207 |
208 | # Unit test / coverage reports
209 | .coverage
210 | .tox
211 |
212 | #Translations
213 | *.mo
214 |
215 | #Mr Developer
216 | .mr.developer.cfg
217 |
218 | ipch/
219 | ffmpeg/
220 | Player/I420Effect_PS.h
221 | Player.VC.db
222 | Player.VC.VC.opendb
223 | *.diagsession
224 |
225 | CMakeLists.txt.user*
226 |
227 | .clang-tidy
228 |
229 | .vs/
230 |
231 | Player/version.h
232 |
233 | build-*/
234 |
235 | Directory.Build.props
236 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Anime4KCPP"]
2 | path = Anime4KCPP
3 | url = https://github.com/TianZerL/Anime4KCPP.git
4 |
--------------------------------------------------------------------------------
/Dlls/Dlls.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Release
5 | {BC1BC9F1-893D-4715-818A-F37F74EB5710}
6 | Library
7 | Properties
8 | Dlls
9 | Dlls
10 | 512
11 |
12 |
13 | true
14 | full
15 | false
16 | bin\Debug\
17 | DEBUG;TRACE
18 | prompt
19 | 4
20 |
21 |
22 | pdbonly
23 | true
24 | bin\Release\
25 | TRACE
26 | prompt
27 | 4
28 |
29 |
30 |
31 | PreserveNewest
32 |
33 |
34 |
35 |
42 |
--------------------------------------------------------------------------------
/HttpDownload/HttpDownload.cpp:
--------------------------------------------------------------------------------
1 | // HttpDownload.cpp : Defines the entry point for the console application.
2 | //
3 |
4 | #include "stdafx.h"
5 |
6 | #include "http_download.h"
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | int _tmain(int argc, TCHAR *argv[])
13 | {
14 | if (argc != 3)
15 | return EXIT_FAILURE;
16 | try
17 | {
18 | const bool ok = HttpDownload(argv[1], argv[2]);
19 | return ok ? EXIT_SUCCESS : EXIT_FAILURE;
20 | }
21 | catch (const std::exception& ex)
22 | {
23 | std::cerr << ex.what() << '\n';
24 | return EXIT_FAILURE;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/HttpDownload/HttpDownload.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 |
29 |
30 | Source Files
31 |
32 |
33 | Source Files
34 |
35 |
36 |
--------------------------------------------------------------------------------
/HttpDownload/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | CONSOLE APPLICATION : HttpDownload Project Overview
3 | ========================================================================
4 |
5 | AppWizard has created this HttpDownload application for you.
6 |
7 | This file contains a summary of what you will find in each of the files that
8 | make up your HttpDownload application.
9 |
10 |
11 | HttpDownload.vcxproj
12 | This is the main project file for VC++ projects generated using an Application Wizard.
13 | It contains information about the version of Visual C++ that generated the file, and
14 | information about the platforms, configurations, and project features selected with the
15 | Application Wizard.
16 |
17 | HttpDownload.vcxproj.filters
18 | This is the filters file for VC++ projects generated using an Application Wizard.
19 | It contains information about the association between the files in your project
20 | and the filters. This association is used in the IDE to show grouping of files with
21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the
22 | "Source Files" filter).
23 |
24 | HttpDownload.cpp
25 | This is the main application source file.
26 |
27 | /////////////////////////////////////////////////////////////////////////////
28 | Other standard files:
29 |
30 | StdAfx.h, StdAfx.cpp
31 | These files are used to build a precompiled header (PCH) file
32 | named HttpDownload.pch and a precompiled types file named StdAfx.obj.
33 |
34 | /////////////////////////////////////////////////////////////////////////////
35 | Other notes:
36 |
37 | AppWizard uses "TODO:" comments to indicate parts of the source code you
38 | should add to or customize.
39 |
40 | /////////////////////////////////////////////////////////////////////////////
41 |
--------------------------------------------------------------------------------
/HttpDownload/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // HttpDownload.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 |
5 | #include "stdafx.h"
6 |
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 |
--------------------------------------------------------------------------------
/HttpDownload/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 |
8 | #include "targetver.h"
9 |
10 | #include
11 | #include
12 |
13 |
14 |
15 | // TODO: reference additional headers your program requires here
16 |
--------------------------------------------------------------------------------
/HttpDownload/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Player/AsyncGetUrlUnderMouseCursor.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | #include "AsyncGetUrlUnderMouseCursor.h"
4 |
5 | namespace {
6 |
7 | class CComUsageScope
8 | {
9 | bool m_bInitialized;
10 | public:
11 | explicit CComUsageScope(DWORD dwCoInit = COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY)
12 | {
13 | m_bInitialized = SUCCEEDED(CoInitializeEx(NULL, dwCoInit));
14 | }
15 | ~CComUsageScope()
16 | {
17 | if (m_bInitialized)
18 | CoUninitialize();
19 | }
20 | };
21 |
22 | bool LinkHandled(const CComPtr& pacc)
23 | {
24 | VARIANT v;
25 | v.vt = VT_I4;
26 | v.lVal = CHILDID_SELF;
27 |
28 | CComVariant vRole;
29 | if (SUCCEEDED(pacc->get_accRole(v, &vRole)) && vRole.vt == VT_I4 && vRole.lVal == ROLE_SYSTEM_LINK)
30 | {
31 | CComBSTR url;
32 | if (SUCCEEDED(pacc->get_accValue(v, &url)) && url != NULL)
33 | {
34 | AfxGetApp()->PostThreadMessage(WM_ON_ASYNC_URL, (WPARAM)url.Detach(), NULL);
35 | return true;
36 | }
37 | }
38 |
39 | return false;
40 | }
41 |
42 | VOID CALLBACK SendAsyncProc(
43 | HWND,
44 | UINT,
45 | ULONG_PTR dwData,
46 | LRESULT lResult)
47 | {
48 | CComUsageScope scope;
49 |
50 | CComPtr pacc_;
51 | if (FAILED(ObjectFromLresult(lResult, __uuidof(IAccessible), 0, (void**)&pacc_)))
52 | return;
53 |
54 | enum { MAX_ITER_NUM = 100 };
55 |
56 | POINT ptScreen{ LOWORD(dwData), HIWORD(dwData) };
57 |
58 | for (int i = 0; i < 2; ++i)
59 | {
60 | CComPtr pacc = pacc_;
61 | {
62 | int iter = 0;
63 | CComVariant vtChild;
64 | CComQIPtr paccChild;
65 | for (; SUCCEEDED(pacc->accHitTest(ptScreen.x, ptScreen.y, &vtChild))
66 | && VT_DISPATCH == vtChild.vt && (paccChild = vtChild.pdispVal) != NULL;
67 | vtChild.Clear())
68 | {
69 | if (LinkHandled(pacc))
70 | return;
71 |
72 | if (iter++ >= MAX_ITER_NUM)
73 | return;
74 | pacc.Attach(paccChild.Detach());
75 | }
76 | }
77 |
78 | int iter = 0;
79 | while (pacc)
80 | {
81 | if (LinkHandled(pacc))
82 | return;
83 |
84 | if (iter++ >= MAX_ITER_NUM)
85 | return;
86 |
87 | CComPtr spDisp;
88 | if (FAILED(pacc->get_accParent(&spDisp)))
89 | return;
90 | CComQIPtr spParent(spDisp);
91 | pacc.Attach(spParent.Detach());
92 | }
93 |
94 | if (i == 0)
95 | {
96 | ::Sleep(100);
97 | }
98 | }
99 | }
100 |
101 | } // namespace
102 |
103 |
104 | void AsyncGetUrlUnderMouseCursor()
105 | {
106 | POINT pt;
107 | if (!GetCursorPos(&pt))
108 | return;
109 |
110 | HWND hWnd = WindowFromPoint(pt);
111 | if (NULL == hWnd)
112 | return;
113 |
114 | TCHAR szBuffer[64];
115 |
116 | const int classNameLength
117 | = ::GetClassName(hWnd, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]));
118 |
119 | szBuffer[sizeof(szBuffer) / sizeof(szBuffer[0]) - 1] = _T('\0');
120 |
121 | if (_tcscmp(szBuffer, _T("MozillaWindowClass")) != 0 && _tcscmp(szBuffer, _T("Chrome_RenderWidgetHostHWND")) != 0)
122 | return;
123 |
124 | VERIFY(SendMessageCallback(hWnd, WM_GETOBJECT, 0L, OBJID_CLIENT, SendAsyncProc, MAKELONG(pt.x, pt.y)));
125 | }
126 |
--------------------------------------------------------------------------------
/Player/AsyncGetUrlUnderMouseCursor.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | enum { WM_ON_ASYNC_URL = 1234 };
4 |
5 | void AsyncGetUrlUnderMouseCursor();
6 |
--------------------------------------------------------------------------------
/Player/ByteStreamBuffer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class ByteStreamBuffer: public std::streambuf
6 | {
7 | public:
8 | ByteStreamBuffer(char* base, size_t length)
9 | {
10 | setg(base, base, base + length);
11 | }
12 |
13 | protected:
14 | pos_type seekoff( off_type offset,
15 | std::ios_base::seekdir dir,
16 | std::ios_base::openmode ) override
17 | {
18 | char* whence = eback();
19 | if (dir == std::ios_base::cur)
20 | {
21 | whence = gptr();
22 | }
23 | else if (dir == std::ios_base::end)
24 | {
25 | whence = egptr();
26 | }
27 | char* to = whence + offset;
28 |
29 | // check limits
30 | if (to >= eback() && to <= egptr())
31 | {
32 | setg(eback(), to, egptr());
33 | return gptr() - eback();
34 | }
35 |
36 | return -1;
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/Player/D3DFONT.H:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------------
2 | // File: D3DFont.h
3 | //
4 | // Desc: Texture-based font class
5 | //-----------------------------------------------------------------------------
6 | #ifndef D3DFONT_H
7 | #define D3DFONT_H
8 | #include
9 | #include
10 |
11 |
12 | // Font creation flags
13 | #define D3DFONT_BOLD 0x0001
14 | #define D3DFONT_ITALIC 0x0002
15 | #define D3DFONT_ZENABLE 0x0004
16 |
17 | // Font rendering flags
18 | #define D3DFONT_CENTERED_X 0x0001
19 | #define D3DFONT_CENTERED_Y 0x0002
20 | #define D3DFONT_TWOSIDED 0x0004
21 | #define D3DFONT_FILTERED 0x0008
22 |
23 |
24 |
25 |
26 | //-----------------------------------------------------------------------------
27 | // Name: class CD3DFont
28 | // Desc: Texture-based font class for doing text in a 3D scene.
29 | //-----------------------------------------------------------------------------
30 | class CD3DFont
31 | {
32 | TCHAR m_strFontName[80]; // Font properties
33 | DWORD m_dwFontHeight;
34 | DWORD m_dwFontFlags;
35 |
36 | LPDIRECT3DDEVICE9 m_pd3dDevice; // A D3DDevice used for rendering
37 | LPDIRECT3DTEXTURE9 m_pTexture; // The d3d texture for this font
38 | LPDIRECT3DVERTEXBUFFER9 m_pVB; // VertexBuffer for rendering text
39 | DWORD m_dwTexWidth {}; // Texture dimensions
40 | DWORD m_dwTexHeight {};
41 | FLOAT m_fTextScale {};
42 | FLOAT m_fTexCoords[128 - 32][4] {};
43 | DWORD m_dwSpacing; // Character pixel spacing per side
44 |
45 | // Stateblocks for setting and restoring render states
46 | LPDIRECT3DSTATEBLOCK9 m_pStateBlockSaved;
47 | LPDIRECT3DSTATEBLOCK9 m_pStateBlockDrawText;
48 |
49 | public:
50 | // 2D and 3D text drawing functions
51 | HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor,
52 | const TCHAR* strText, DWORD dwFlags=0L );
53 | HRESULT DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
54 | FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
55 | const TCHAR* strText, DWORD dwFlags=0L );
56 | HRESULT Render3DText( const TCHAR* strText, DWORD dwFlags=0L );
57 |
58 | // Function to get extent of text
59 | HRESULT GetTextExtent( const TCHAR* strText, SIZE* pSize );
60 |
61 | // Initializing and destroying device-dependent objects
62 | HRESULT InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice );
63 | HRESULT RestoreDeviceObjects();
64 | HRESULT InvalidateDeviceObjects();
65 | HRESULT DeleteDeviceObjects();
66 |
67 | // Constructor / destructor
68 | CD3DFont( const TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags=0L );
69 | ~CD3DFont();
70 | };
71 |
72 |
73 |
74 |
75 | #endif
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Player/DialogBarPlayerControl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "afxcmn.h"
4 |
5 | class CPlayerDoc;
6 |
7 | // CDialogBarPlayerControl
8 |
9 | class CDialogBarPlayerControl
10 | : public CPaneDialog
11 | {
12 | DECLARE_DYNAMIC(CDialogBarPlayerControl)
13 |
14 | public:
15 | CDialogBarPlayerControl();
16 | virtual ~CDialogBarPlayerControl();
17 |
18 | // Dialog Data
19 | //{{AFX_DATA(CDialogBarPlayerControl)
20 | enum { IDD = IDD_DIALOGBAR_PLAYER_CONTROL };
21 | // NOTE: the ClassWizard will add data members here
22 | //}}AFX_DATA
23 |
24 | void setDocument(CPlayerDoc* pDoc);
25 |
26 | // Overrides
27 | // ClassWizard generated virtual function overrides
28 | //{{AFX_VIRTUAL(CDialogBarPlayerControl)
29 | protected:
30 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
31 | //}}AFX_VIRTUAL
32 |
33 | int GetCaptionHeight() const override { return 0; }
34 |
35 | void onFramePositionChanged(long long frame, long long total);
36 | void onTotalTimeUpdated(double secs);
37 | void onCurrentTimeUpdated(double secs);
38 |
39 | void onRangeStartTimeChanged(long long frame, long long total);
40 | void onRangeEndTimeChanged(long long frame, long long total);
41 |
42 | void onDocDetaching();
43 |
44 | protected:
45 | DECLARE_MESSAGE_MAP()
46 | afx_msg LRESULT HandleInitDialog(WPARAM wParam, LPARAM lParam);
47 | afx_msg LRESULT OnSetTime(WPARAM wParam, LPARAM lParam);
48 | public:
49 |
50 | private:
51 | CPlayerDoc* m_pDoc;
52 | HICON m_hPlay;
53 | HICON m_hPause;
54 | HICON m_hAudio;
55 | HICON m_hAudioOff;
56 | HICON m_hFullScreen;
57 | int m_savedVolume;
58 | volatile int m_oldTotalTime;
59 | volatile int m_oldCurrentTime;
60 | bool m_tracking;
61 |
62 | int m_selStart;
63 | int m_selEnd;
64 |
65 | public:
66 | CSliderCtrl m_progressSlider;
67 | CSliderCtrl m_volumeSlider;
68 | afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
69 | afx_msg void OnUpdatePlayPause(CCmdUI *pCmdUI);
70 | afx_msg void OnUpdateAudioOnOff(CCmdUI *pCmdUI);
71 | afx_msg void OnClickedPlayPause();
72 | afx_msg void OnClickedAudioOnOff();
73 | afx_msg void OnUpdateFrameStep(CCmdUI *pCmdUI);
74 | afx_msg void OnUpdateVolumeSlider(CCmdUI *pCmdUI);
75 | afx_msg void OnUpdateCurrentTime(CCmdUI *pCmdUI);
76 | };
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Player/DialogBarRange.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "EditTime.h"
4 |
5 | class CPlayerDoc;
6 |
7 | // CDialogBarRange
8 |
9 | class CDialogBarRange : public CPaneDialog
10 | {
11 | DECLARE_DYNAMIC(CDialogBarRange)
12 |
13 | public:
14 | CDialogBarRange();
15 | virtual ~CDialogBarRange();
16 |
17 | enum { IDD = IDD_DIALOGBAR_RANGE };
18 |
19 | void setDocument(CPlayerDoc* pDoc);
20 |
21 | // Overrides
22 | // ClassWizard generated virtual function overrides
23 | //{{AFX_VIRTUAL(CDialogBarPlayerControl)
24 | protected:
25 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
26 | //}}AFX_VIRTUAL
27 |
28 | protected:
29 | int GetCaptionHeight() const override { return 0; }
30 |
31 | void onTotalTimeUpdated(double secs);
32 |
33 | void onDocDetaching();
34 |
35 | protected:
36 | DECLARE_MESSAGE_MAP()
37 | afx_msg LRESULT HandleInitDialog(WPARAM wParam, LPARAM lParam);
38 | private:
39 | CPlayerDoc* m_pDoc;
40 | CFont m_font;
41 | public:
42 | CEditTime m_startTime;
43 | CEditTime m_endTime;
44 | afx_msg void OnStart();
45 | afx_msg void OnStartReset();
46 | afx_msg void OnEnd();
47 | afx_msg void OnEndReset();
48 | afx_msg void OnUpdateStart(CCmdUI *pCmdUI);
49 | afx_msg void OnUpdateStartReset(CCmdUI *pCmdUI);
50 | afx_msg void OnUpdateEnd(CCmdUI *pCmdUI);
51 | afx_msg void OnUpdateEndReset(CCmdUI *pCmdUI);
52 | afx_msg void OnUpdateSave(CCmdUI *pCmdUI);
53 | afx_msg void OnChangeStart();
54 | afx_msg void OnChangeEnd();
55 | afx_msg void OnBnClickedLosslessCut();
56 | };
57 |
--------------------------------------------------------------------------------
/Player/DialogOpenURL.cpp:
--------------------------------------------------------------------------------
1 | // DialogOpenURL.cpp : implementation file
2 | //
3 |
4 | #include "stdafx.h"
5 | #include "Player.h"
6 | #include "DialogOpenURL.h"
7 | #include "afxdialogex.h"
8 |
9 |
10 | // CDialogOpenURL dialog
11 |
12 | IMPLEMENT_DYNAMIC(CDialogOpenURL, CDialog)
13 |
14 | CDialogOpenURL::CDialogOpenURL(CWnd* pParent /*=NULL*/)
15 | : CDialog(IDD_DIALOG_OPEN_URL, pParent)
16 | , m_URL(_T(""))
17 | , m_bParse(false)
18 | , m_inputFormt(_T(""))
19 | {
20 |
21 | }
22 |
23 | CDialogOpenURL::~CDialogOpenURL()
24 | {
25 | }
26 |
27 | void CDialogOpenURL::DoDataExchange(CDataExchange* pDX)
28 | {
29 | CDialog::DoDataExchange(pDX);
30 | DDX_Text(pDX, IDC_EDIT_URL, m_URL);
31 | DDX_Check(pDX, IDC_PARSE, m_bParse);
32 | DDX_Text(pDX, IDC_EDIT_INPUT_FORMAT, m_inputFormt);
33 | }
34 |
35 |
36 | BEGIN_MESSAGE_MAP(CDialogOpenURL, CDialog)
37 | END_MESSAGE_MAP()
38 |
39 |
40 | // CDialogOpenURL message handlers
41 |
--------------------------------------------------------------------------------
/Player/DialogOpenURL.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 |
4 | // CDialogOpenURL dialog
5 |
6 | class CDialogOpenURL : public CDialog
7 | {
8 | DECLARE_DYNAMIC(CDialogOpenURL)
9 |
10 | public:
11 | explicit CDialogOpenURL(CWnd* pParent = NULL); // standard constructor
12 | virtual ~CDialogOpenURL();
13 |
14 | // Dialog Data
15 | #ifdef AFX_DESIGN_TIME
16 | enum { IDD = IDD_DIALOG_OPEN_URL };
17 | #endif
18 |
19 | protected:
20 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
21 |
22 | DECLARE_MESSAGE_MAP()
23 | public:
24 | CString m_URL;
25 | int m_bParse{};
26 | CString m_inputFormt;
27 | };
28 |
--------------------------------------------------------------------------------
/Player/EditTime.cpp:
--------------------------------------------------------------------------------
1 | // EditTime.cpp : implementation file
2 | //
3 |
4 | #include "stdafx.h"
5 | #include "EditTime.h"
6 | #include "SecondsToString.h"
7 |
8 | #include
9 |
10 | #ifdef _DEBUG
11 | #define new DEBUG_NEW
12 | #undef THIS_FILE
13 | static char THIS_FILE[] = __FILE__;
14 | #endif
15 |
16 | namespace {
17 |
18 |
19 | enum
20 | {
21 | TIME_INVALID = -1000000000
22 | };
23 |
24 | int ReadUint(const TCHAR*& s)
25 | {
26 | int buf = 0;
27 | for (; *s >= '0' && *s <= '9'; ++s)
28 | buf = buf * 10 + *s - '0';
29 |
30 | return buf;
31 | }
32 |
33 | double ParseTime(const TCHAR* timeStr)
34 | {
35 | int seconds = 0;
36 |
37 | int numDelims = 0;
38 |
39 | const bool minus = *timeStr == '-';
40 | if (minus)
41 | ++timeStr;
42 |
43 | for (;;)
44 | {
45 | switch (*timeStr)
46 | {
47 | case '\0':
48 | return minus ? -seconds : seconds;
49 | case ':':
50 | if (++numDelims > 2)
51 | return TIME_INVALID;
52 | seconds *= 60;
53 | ++timeStr;
54 | break;
55 | case '.':
56 | {
57 | ++timeStr;
58 | const auto prevPtr = timeStr;
59 | const auto millis = ReadUint(timeStr);
60 | if (*timeStr != '\0')
61 | return TIME_INVALID;
62 | const int msecStringLen = timeStr - prevPtr;
63 | if (msecStringLen > 3)
64 | return TIME_INVALID;
65 | if (msecStringLen == 0)
66 | return minus ? -seconds : seconds;
67 | const auto absResult = seconds + millis / std::pow(10, msecStringLen);
68 | return minus ? -absResult : absResult;
69 | }
70 | break;
71 | default:
72 | const auto prevPtr = timeStr;
73 | seconds += ReadUint(timeStr);
74 | if (prevPtr == timeStr)
75 | return TIME_INVALID;
76 | }
77 | }
78 | }
79 |
80 | bool Match(const TCHAR* timeStr)
81 | {
82 | return ParseTime(timeStr) != TIME_INVALID;
83 | }
84 |
85 | } // namespace
86 |
87 |
88 | enum { WM_RESET = WM_USER + 101 };
89 |
90 | /////////////////////////////////////////////////////////////////////////////
91 | // CEditTime
92 |
93 | CEditTime::CEditTime()
94 | {
95 | }
96 |
97 | CEditTime::~CEditTime()
98 | {
99 | }
100 |
101 | BEGIN_MESSAGE_MAP(CEditTime, CEdit)
102 | //{{AFX_MSG_MAP(CEditTime)
103 | ON_WM_CHAR()
104 | ON_MESSAGE(WM_RESET, &CEditTime::OnReset)
105 | //}}AFX_MSG_MAP
106 | END_MESSAGE_MAP()
107 |
108 | /////////////////////////////////////////////////////////////////////////////
109 | // CEditTime message handlers
110 |
111 | void CEditTime::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
112 | {
113 | if (nChar >= 32)
114 | {
115 | int iStartIndex = -1;
116 | int iEndIndex = -1;
117 |
118 | GetSel(iStartIndex, iEndIndex);
119 | CString strProposedText;
120 | GetWindowText(strProposedText);
121 | strProposedText.Delete(iStartIndex, iEndIndex - iStartIndex);
122 | strProposedText.Insert(iStartIndex, static_cast(nChar));
123 |
124 | if (!Match(strProposedText))
125 | return;
126 | }
127 | CEdit::OnChar(nChar, nRepCnt, nFlags);
128 | }
129 |
130 | void CEditTime::Reset()
131 | {
132 | SendNotifyMessage(WM_RESET, 0, 0);
133 | }
134 |
135 | void CEditTime::SetValue(double fTime)
136 | {
137 | SetWindowText(secondsToString(fTime * 1000, true).c_str());
138 | }
139 |
140 | double CEditTime::GetValue() const
141 | {
142 | CString strBuf;
143 | GetWindowText(strBuf);
144 | return ParseTime(strBuf);
145 | }
146 |
147 | bool CEditTime::IsEmpty() const
148 | {
149 | CString strBuf;
150 | GetWindowText(strBuf);
151 | return strBuf.IsEmpty();
152 | }
153 |
154 | LRESULT CEditTime::OnReset(WPARAM, LPARAM)
155 | {
156 | SetWindowText(_T(""));
157 | return 0;
158 | }
159 |
--------------------------------------------------------------------------------
/Player/EditTime.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /////////////////////////////////////////////////////////////////////////////
4 | // CEditTime window
5 |
6 | class CEditTime : public CEdit
7 | {
8 | // Construction
9 | public:
10 | CEditTime();
11 |
12 | // Attributes
13 | public:
14 | void Reset();
15 | void SetValue(double fTime);
16 | double GetValue() const;
17 | bool IsEmpty() const;
18 |
19 | // Operations
20 |
21 | // Overrides
22 | // ClassWizard generated virtual function overrides
23 | //{{AFX_VIRTUAL(CEditTime)
24 | //}}AFX_VIRTUAL
25 |
26 | // Implementation
27 | public:
28 | virtual ~CEditTime();
29 |
30 | // Generated message map functions
31 | protected:
32 | //{{AFX_MSG(CEditTime)
33 | afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
34 | afx_msg LRESULT OnReset(WPARAM wParam, LPARAM lParam);
35 | //}}AFX_MSG
36 |
37 | DECLARE_MESSAGE_MAP()
38 |
39 | private:
40 | CFont m_Font;
41 | };
42 |
43 | /////////////////////////////////////////////////////////////////////////////
44 |
45 | //{{AFX_INSERT_LOCATION}}
46 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line.
47 |
48 |
--------------------------------------------------------------------------------
/Player/FrameToHglobal.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "FrameToHglobal.h"
3 |
4 | #include "ffmpeg_dxva2.h"
5 |
6 | extern "C"
7 | {
8 | #include "libavutil/frame.h"
9 | #include "libswscale/swscale.h"
10 | };
11 |
12 | HGLOBAL FrameToHglobal(IDirect3DSurface9* surface, int width, int height, int allocatedHeight)
13 | {
14 | AVFrame* tmp_frame = av_frame_alloc();
15 |
16 | int res = dxva2_convert_data(surface, tmp_frame, width, allocatedHeight);
17 | if (res != 0)
18 | {
19 | av_frame_free(&tmp_frame);
20 | return NULL;
21 | }
22 |
23 | const int stride = ((width * 3) + 3) & ~3;
24 |
25 | auto hMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(BITMAPINFOHEADER) + stride * height);
26 |
27 | if (hMem == NULL) {
28 | av_frame_free(&tmp_frame);
29 | return NULL;
30 | }
31 |
32 | auto bmi = static_cast(GlobalLock(hMem));
33 | if (!bmi) {
34 | GlobalFree(hMem);
35 | av_frame_free(&tmp_frame);
36 | return NULL;
37 | }
38 |
39 | memset(bmi, 0, sizeof(BITMAPINFOHEADER));
40 | bmi->biSize = sizeof(BITMAPINFOHEADER);
41 | bmi->biWidth = width;
42 | bmi->biHeight = -height;
43 |
44 | bmi->biPlanes = 1;
45 | bmi->biBitCount = 24;
46 | bmi->biCompression = BI_RGB;
47 |
48 | const auto pData = static_cast(static_cast(bmi + 1));
49 |
50 | auto img_convert_ctx = sws_getContext(tmp_frame->width, tmp_frame->height, (AVPixelFormat)tmp_frame->format,
51 | width, allocatedHeight, AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
52 |
53 | sws_scale(img_convert_ctx, tmp_frame->data, tmp_frame->linesize, 0, height,
54 | &pData, &stride);
55 |
56 | sws_freeContext(img_convert_ctx);
57 |
58 | GlobalUnlock(hMem);
59 | av_frame_free(&tmp_frame);
60 |
61 | return hMem;
62 | }
63 |
--------------------------------------------------------------------------------
/Player/FrameToHglobal.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct IDirect3DSurface9;
4 |
5 | HGLOBAL FrameToHglobal(IDirect3DSurface9* surface, int width, int height, int allocatedHeight);
6 |
--------------------------------------------------------------------------------
/Player/GetClipboardText.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | inline std::string GetClipboardText()
6 | {
7 | std::string text;
8 |
9 | // Try opening the clipboard
10 | if (OpenClipboard(nullptr))
11 | {
12 | // Get handle of clipboard object for ANSI text
13 | if (HANDLE hData = GetClipboardData(CF_TEXT))
14 | {
15 | // Lock the handle to get the actual text pointer
16 | if (const char* pszText = static_cast(GlobalLock(hData)))
17 | {
18 | // Save text in a string class instance
19 | text = pszText;
20 | }
21 | // Release the lock
22 | GlobalUnlock(hData);
23 | }
24 |
25 | // Release the clipboard
26 | CloseClipboard();
27 | }
28 |
29 | return text;
30 | }
31 |
--------------------------------------------------------------------------------
/Player/HandleFilesSequence.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | #include "HandleFilesSequence.h"
4 |
5 | #include
6 | #include
7 |
8 | namespace {
9 |
10 | auto MakeComparableConsideringNumbers(const CString& s)
11 | {
12 | std::vector result;
13 |
14 | unsigned int accum = 0;
15 | for (int i = 0; i < s.GetLength(); ++i)
16 | {
17 | const auto c = s[i];
18 | if ((c >= _T('0') && accum != 0 || c > _T('0')) && c <= _T('9'))
19 | {
20 | accum = accum * 10 + (c - _T('0'));
21 | }
22 | else
23 | {
24 | if (accum != 0)
25 | {
26 | result.push_back(accum + static_cast(_T('0')));
27 | accum = 0;
28 | }
29 | result.push_back((static_cast(c) < static_cast(_T('9')))
30 | ? c : (0xFFFF0000 | c));
31 | }
32 | }
33 |
34 | if (accum != 0)
35 | {
36 | result.push_back(accum + static_cast(_T('0')));
37 | }
38 |
39 | return result;
40 | }
41 |
42 | bool CompareConsideringNumbers(CString left, CString right)
43 | {
44 | const auto leftConverted = MakeComparableConsideringNumbers(left.MakeUpper());
45 | const auto rightConverted = MakeComparableConsideringNumbers(right.MakeUpper());
46 |
47 | return std::lexicographical_compare(
48 | rightConverted.begin(), rightConverted.end(), leftConverted.begin(), leftConverted.end());
49 | }
50 |
51 | }
52 |
53 | bool HandleFilesSequence(const CString& pathName,
54 | bool looping,
55 | std::function tryToOpen,
56 | bool invert /*= false*/)
57 | {
58 | const auto extension = PathFindExtension(pathName);
59 | const auto fileName = PathFindFileName(pathName);
60 | if (!extension || !fileName)
61 | return false;
62 | const CString directory(pathName, fileName - pathName);
63 | const CString pattern((directory + _T('*')) + extension);
64 |
65 | WIN32_FIND_DATA ffd{};
66 | const auto hFind = FindFirstFile(pattern, &ffd);
67 |
68 | if (INVALID_HANDLE_VALUE == hFind)
69 | {
70 | return false;
71 | }
72 |
73 | std::vector filesArr[2];
74 | const auto extensionLength = pathName.GetLength() - (extension - pathName);
75 | const CString justFileName(fileName, extension - fileName);
76 |
77 | do
78 | {
79 | if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
80 | {
81 | const auto length = _tcslen(ffd.cFileName);
82 | if (length > extensionLength && ffd.cFileName[length - extensionLength] == _T('.'))
83 | {
84 | CString cFileName(ffd.cFileName, length - extensionLength);
85 | const bool beforeOrEqual = !CompareConsideringNumbers(cFileName, justFileName);
86 | filesArr[beforeOrEqual].push_back(cFileName);
87 | }
88 | }
89 | } while (FindNextFile(hFind, &ffd));
90 |
91 | FindClose(hFind);
92 |
93 | for (int i = 0; i <= looping; ++i)
94 | {
95 | std::vector& files = filesArr[i ^ invert];
96 | std::make_heap(files.begin(), files.end(), CompareConsideringNumbers);
97 |
98 | while (!files.empty())
99 | {
100 | const CString path = directory + files.front() + extension;
101 | if (tryToOpen(path))
102 | {
103 | return true;
104 | }
105 | std::pop_heap(files.begin(), files.end(), CompareConsideringNumbers);
106 | files.pop_back();
107 | }
108 | }
109 | return false;
110 | }
111 |
--------------------------------------------------------------------------------
/Player/HandleFilesSequence.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | bool HandleFilesSequence(const CString& pathName,
6 | bool looping,
7 | std::function tryToOpen,
8 | bool invert = false);
9 |
--------------------------------------------------------------------------------
/Player/I420Effect.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | // {3AB41678-D4BC-4BE1-8A91-07A63DEEFEA1}
6 | DEFINE_GUID(GUID_I420PixelShader, 0x3ab41678, 0xd4bc, 0x4be1, 0x8a, 0x91, 0x7, 0xa6, 0x3d, 0xee, 0xfe, 0xa1);
7 | // {DA637E40-44D4-4617-A3D3-A28344549EEA}
8 | DEFINE_GUID(CLSID_CustomI420Effect, 0xda637e40, 0x44d4, 0x4617, 0xa3, 0xd3, 0xa2, 0x83, 0x44, 0x54, 0x9e, 0xea);
9 |
10 | class I420Effect : public ID2D1EffectImpl, public ID2D1DrawTransform
11 | {
12 | public:
13 | // Declare effect registration methods.
14 | static HRESULT Register(_In_ ID2D1Factory1* pFactory);
15 | static HRESULT __stdcall CreateRippleImpl(_Outptr_ IUnknown** ppEffectImpl);
16 |
17 | // Declare ID2D1EffectImpl implementation methods.
18 | IFACEMETHODIMP Initialize(_In_ ID2D1EffectContext* pContextInternal, _In_ ID2D1TransformGraph* pTransformGraph);
19 | IFACEMETHODIMP PrepareForRender(D2D1_CHANGE_TYPE changeType);
20 | IFACEMETHODIMP SetGraph(_In_ ID2D1TransformGraph* pGraph);
21 |
22 | // Declare ID2D1DrawTransform implementation methods.
23 | IFACEMETHODIMP SetDrawInfo(_In_ ID2D1DrawInfo* pRenderInfo);
24 |
25 | // Declare ID2D1Transform implementation methods.
26 | IFACEMETHODIMP MapOutputRectToInputRects(
27 | _In_ const D2D1_RECT_L* pOutputRect,
28 | _Out_writes_(inputRectCount) D2D1_RECT_L* pInputRects,
29 | UINT32 inputRectCount
30 | ) const;
31 |
32 | IFACEMETHODIMP MapInputRectsToOutputRect(
33 | _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputRects,
34 | _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputOpaqueSubRects,
35 | UINT32 inputRectCount,
36 | _Out_ D2D1_RECT_L* pOutputRect,
37 | _Out_ D2D1_RECT_L* pOutputOpaqueSubRect
38 | );
39 |
40 | IFACEMETHODIMP MapInvalidRect(
41 | UINT32 inputIndex,
42 | D2D1_RECT_L invalidInputRect,
43 | _Out_ D2D1_RECT_L* pInvalidOutputRect
44 | ) const;
45 |
46 | // Declare ID2D1TransformNode implementation methods.
47 | IFACEMETHODIMP_(UINT32) GetInputCount() const;
48 |
49 | // Declare IUnknown implementation methods.
50 | IFACEMETHODIMP_(ULONG) AddRef();
51 | IFACEMETHODIMP_(ULONG) Release();
52 | IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _Outptr_ void** ppOutput);
53 | private:
54 |
55 | I420Effect();
56 |
57 | CComPtr m_drawInfo;
58 |
59 | LONG m_refCount;
60 | D2D1_RECT_L m_inputRect;
61 | D2D1_SIZE_U m_originalFrame;
62 | };
63 |
--------------------------------------------------------------------------------
/Player/I420Effect_PS.hlsl:
--------------------------------------------------------------------------------
1 | Texture2D yTexture : register(t0);
2 | Texture2D uTexture : register(t1);
3 | Texture2D vTexture : register(t2);
4 |
5 | SamplerState ySampler : register(s0);
6 | SamplerState uSampler : register(s1);
7 | SamplerState vSampler : register(s2);
8 |
9 | float4 main(
10 | float4 pos : SV_POSITION,
11 | float4 posScene : SCENE_POSITION,
12 | float4 uv0 : TEXCOORD0
13 | ) : SV_Target
14 | {
15 | float Y = yTexture.Sample(ySampler, uv0).a * 255;
16 | float U = uTexture.Sample(uSampler, uv0).a * 255;
17 | float V = vTexture.Sample(vSampler, uv0).a * 255;
18 |
19 | float4 color = float4(0, 0, 0, 1.0f);
20 |
21 | color.b = clamp(1.164383561643836*(Y - 16) + 2.017232142857142*(U - 128), 0, 255) / 255.0f;
22 | color.g = clamp(1.164383561643836*(Y - 16) - 0.812967647237771*(V - 128) - 0.391762290094914*(U - 128), 0, 255) / 255.0f;
23 | color.r = clamp(1.164383561643836*(Y - 16) + 1.596026785714286*(V - 128), 0, 255) / 255.0f;
24 |
25 | return color;
26 | }
--------------------------------------------------------------------------------
/Player/IEraseableArea.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class CWnd;
4 | class CDC;
5 |
6 | class IEraseableArea
7 | {
8 | public:
9 | virtual void OnErase(CWnd* pInitiator, CDC* pDC, BOOL isFullScreen) = 0;
10 | };
11 |
--------------------------------------------------------------------------------
/Player/ImageUpscale.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | #include "ImageUpscale.h"
4 |
5 | #if __has_include("AC.hpp")
6 |
7 | #include"AC.hpp"
8 | #include"ACCreator.hpp"
9 | #include"ACProcessor.hpp"
10 | #include "Anime4KCPP.hpp"
11 |
12 |
13 | const int currPlatformID = 0;
14 | const int currDeviceID = 0;
15 |
16 | bool CanUpscaleImage()
17 | {
18 | static const bool ok = LoadLibrary(_T("opencl.dll")) != NULL
19 | && Anime4KCPP::OpenCL::checkGPUSupport(currPlatformID, currDeviceID);
20 | return ok;
21 | }
22 |
23 | bool EnableImageUpscale()
24 | {
25 | static Anime4KCPP::ACInitializer initializer;
26 |
27 | static const auto ok = [] {
28 | const int OpenCLQueueNum = 1;
29 | const bool OpenCLParallelIO = false;
30 |
31 | initializer.pushManager>(
32 | currPlatformID, currDeviceID,
33 | Anime4KCPP::CNNType::Default,
34 | OpenCLQueueNum,
35 | OpenCLParallelIO);
36 |
37 | return initializer.init() == initializer.size();
38 | }();
39 | return ok;
40 | }
41 |
42 | void ImageUpscale(uint8_t* input, int inputStride, int inputWidth, int inputHeight, std::vector& output, int& outputWidth, int& outputHeight)
43 | {
44 | Anime4KCPP::Parameters param{};
45 | auto ac = Anime4KCPP::ACCreator::createUP(param, Anime4KCPP::Processor::Type::OpenCL_ACNet);
46 |
47 | const cv::Mat y_image(inputHeight, inputWidth, CV_8UC1, input, inputStride);
48 | const cv::Mat uv_image(inputHeight / 2, inputWidth / 2, CV_8UC2, input + inputHeight * inputStride, inputStride);
49 | cv::Mat cbcr_channels[2];
50 | split(uv_image, cbcr_channels);
51 |
52 | ac->loadImage(y_image, cbcr_channels[0], cbcr_channels[1]);
53 |
54 | ac->process();
55 |
56 | cv::Mat out_y_image;
57 | std::vector out_cbcr_channels(2);
58 |
59 | ac->saveImage(out_y_image, out_cbcr_channels[0], out_cbcr_channels[1]);
60 |
61 | outputWidth = out_y_image.cols;
62 | outputHeight = out_y_image.rows;
63 |
64 | cv::Mat CrCb;
65 | merge(out_cbcr_channels, CrCb);
66 |
67 | output.assign(out_y_image.datastart, out_y_image.dataend);
68 | output.insert(output.end(), CrCb.datastart, CrCb.dataend);
69 | }
70 |
71 | #else
72 |
73 | bool CanUpscaleImage()
74 | {
75 | return false;
76 | }
77 |
78 | bool EnableImageUpscale()
79 | {
80 | return false;
81 | }
82 |
83 | void ImageUpscale(uint8_t*, int, int, int, std::vector&, int&, int&)
84 | {
85 | }
86 |
87 | #endif
88 |
--------------------------------------------------------------------------------
/Player/ImageUpscale.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | bool CanUpscaleImage();
7 |
8 | bool EnableImageUpscale();
9 |
10 | void ImageUpscale(uint8_t* input, int inputStride, int inputWidth, int inputHeight, std::vector& output, int& outputWidth, int& outputHeight);
11 |
--------------------------------------------------------------------------------
/Player/MainFrm.h:
--------------------------------------------------------------------------------
1 |
2 | // MainFrm.h : interface of the CMainFrame class
3 | //
4 |
5 | #pragma once
6 |
7 | #include "DialogBarPlayerControl.h"
8 | #include "DialogBarRange.h"
9 |
10 | struct ITaskbarList3;
11 |
12 | class CMainFrame : public CFrameWndEx
13 | {
14 |
15 | protected: // create from serialization only
16 | CMainFrame();
17 | DECLARE_DYNCREATE(CMainFrame)
18 |
19 | // Attributes
20 | public:
21 |
22 | // Operations
23 | private:
24 | void pauseResume();
25 | void onPauseResume(bool paused);
26 |
27 |
28 | // Overrides
29 | public:
30 | BOOL OnCommand(WPARAM wParam, LPARAM lParam) override;
31 | BOOL PreCreateWindow(CREATESTRUCT& cs) override;
32 |
33 | BOOL Create(LPCTSTR lpszClassName,
34 | LPCTSTR lpszWindowName,
35 | DWORD dwStyle = WS_OVERLAPPEDWINDOW,
36 | const RECT& rect = rectDefault,
37 | CWnd* pParentWnd = NULL, // != NULL for popups
38 | LPCTSTR lpszMenuName = NULL,
39 | DWORD dwExStyle = 0,
40 | CCreateContext* pContext = NULL) override;
41 |
42 | BOOL PreTranslateMessage(MSG* pMsg) override;
43 |
44 |
45 | // Implementation
46 | public:
47 | virtual ~CMainFrame();
48 | #ifdef _DEBUG
49 | virtual void AssertValid() const;
50 | virtual void Dump(CDumpContext& dc) const;
51 | #endif
52 |
53 | protected: // control bar embedded members
54 | CMFCMenuBar m_wndMenuBar;
55 | //CMFCToolBar m_wndToolBar;
56 | //CMFCStatusBar m_wndStatusBar;
57 | CDialogBarPlayerControl m_wndPlayerControl;
58 | CDialogBarRange m_wndRange;
59 |
60 | BOOL m_bFullScreen;
61 |
62 | CComPtr m_pTaskbarList;
63 |
64 | HICON m_hPlay;
65 | HICON m_hPause;
66 |
67 | // Generated message map functions
68 | protected:
69 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
70 | afx_msg void OnClose();
71 | afx_msg LRESULT CreateThumbnailToolbar(WPARAM wParam, LPARAM lParam);
72 | afx_msg void OnFullScreen();
73 | afx_msg BOOL OnEraseBkgnd(CDC* pDC);
74 | afx_msg void OnWindowPosChanged(WINDOWPOS* lpwndpos);
75 | afx_msg void OnNcPaint();
76 | afx_msg UINT OnPowerBroadcast(UINT nPowerEvent, LPARAM nEventData);
77 | afx_msg LRESULT OnNcHitTest(CPoint point);
78 | DECLARE_MESSAGE_MAP()
79 | public:
80 | afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
81 | };
82 |
--------------------------------------------------------------------------------
/Player/MakeDelegate.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | template
6 | class Delegate
7 | {
8 | public:
9 | explicit Delegate(T* callee)
10 | : fpCallee(callee)
11 | {}
12 | template
13 | decltype(auto) operator()(Args&&... xs) const
14 | {
15 | return (fpCallee->*TMethod)(std::forward(xs)...);
16 | }
17 |
18 | bool operator == (const Delegate& other) const
19 | {
20 | return fpCallee == other.fpCallee;
21 | }
22 |
23 | bool operator != (const Delegate& other) const
24 | {
25 | return fpCallee != other.fpCallee;
26 | }
27 |
28 | private:
29 | T* fpCallee;
30 | };
31 |
32 |
33 | template
34 | inline auto MakeDelegate(T* ptr)
35 | {
36 | return Delegate(ptr);
37 | }
38 |
39 | #define MAKE_DELEGATE(foo, thisPtr) (MakeDelegate(thisPtr))
40 |
--------------------------------------------------------------------------------
/Player/MemoryMappedFile.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class MemoryMappedFile
4 | {
5 | public:
6 | MemoryMappedFile()
7 | : hFile(INVALID_HANDLE_VALUE)
8 | , hFileMapping(NULL)
9 | , pData(NULL)
10 | {}
11 | ~MemoryMappedFile()
12 | {
13 | if (pData)
14 | UnmapViewOfFile(pData);
15 | if (hFileMapping)
16 | CloseHandle(hFileMapping);
17 | if (INVALID_HANDLE_VALUE != hFile)
18 | CloseHandle(hFile);
19 | }
20 | MemoryMappedFile(const MemoryMappedFile&) = delete;
21 | MemoryMappedFile& operator=(const MemoryMappedFile&) = delete;
22 |
23 | bool MapFlie(LPCTSTR szFile)
24 | {
25 | hFile = CreateFile(
26 | szFile, // pointer to name of the file
27 | GENERIC_READ, // access (read-write) mode
28 | FILE_SHARE_READ, // share mode
29 | NULL, // pointer to security attributes
30 | OPEN_EXISTING, // how to create
31 | FILE_ATTRIBUTE_NORMAL, // file attributes
32 | NULL // handle to file with attributes to copy
33 | );
34 | if (INVALID_HANDLE_VALUE != hFile && GetFileSizeEx(hFile, &fileSize) && fileSize.HighPart == 0)
35 | {
36 | hFileMapping = CreateFileMapping(
37 | hFile, // handle to file to map
38 | NULL, // optional security attributes
39 | PAGE_READONLY, // protection for mapping object
40 | fileSize.HighPart, // high-order 32 bits of object size
41 | fileSize.LowPart, // low-order 32 bits of object size
42 | NULL // name of file-mapping object
43 | );
44 | if (NULL != hFileMapping)
45 | {
46 | pData = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, (SIZE_T)fileSize.QuadPart);
47 | return pData != NULL;
48 | }
49 | }
50 |
51 | return false;
52 | }
53 |
54 | LPVOID data() const { return pData; }
55 | LONGLONG size() const { return fileSize.QuadPart; }
56 |
57 | private:
58 | HANDLE hFile;
59 | LARGE_INTEGER fileSize;
60 | HANDLE hFileMapping;
61 | LPVOID pData;
62 | };
63 |
--------------------------------------------------------------------------------
/Player/OpenSubtitlesFile.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | typedef std::function AddIntervalCallback;
8 |
9 |
10 | bool OpenSubtitlesFile(const TCHAR* videoPathName,
11 | bool& unicodeSubtitles,
12 | AddIntervalCallback addIntervalCallback);
13 |
14 | bool OpenMatchingSubtitlesFile(const TCHAR* videoPathName,
15 | bool& unicodeSubtitles,
16 | AddIntervalCallback addIntervalCallback);
17 |
--------------------------------------------------------------------------------
/Player/Player.h:
--------------------------------------------------------------------------------
1 |
2 | // Player.h : main header file for the Player application
3 | //
4 | #pragma once
5 |
6 | #ifndef __AFXWIN_H__
7 | #error "include 'stdafx.h' before including this file for PCH"
8 | #endif
9 |
10 | #include "resource.h" // main symbols
11 |
12 | class CPlayerDoc;
13 |
14 | // CPlayerApp:
15 | // See Player.cpp for the implementation of this class
16 | //
17 |
18 | class CPlayerApp : public CWinAppEx
19 | {
20 | public:
21 | CPlayerApp();
22 |
23 |
24 | // Overrides
25 | public:
26 | BOOL InitInstance() override;
27 |
28 | CString GetMappedAudioFile(LPCTSTR key);
29 | void SetMappedAudioFile(LPCTSTR key, LPCTSTR value);
30 |
31 | // Implementation
32 | afx_msg void OnAppAbout();
33 | afx_msg void OnAsyncUrl(WPARAM wParam, LPARAM lParam);
34 | DECLARE_MESSAGE_MAP()
35 |
36 | CPlayerDoc* GetPlayerDocument();
37 |
38 | private:
39 | bool GetMappedAudioFiles(CMapStringToString& map);
40 | void SetMappedAudioFiles(CMapStringToString& map);
41 |
42 | void HandleMruList();
43 | };
44 |
45 | extern CPlayerApp theApp;
46 |
47 | enum { ID_FIRST_SUBTITLE = 7000, ID_TRACK1 = 7100 };
48 |
--------------------------------------------------------------------------------
/Player/Player.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/Player.rc
--------------------------------------------------------------------------------
/Player/PlayerView.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "IEraseableArea.h"
4 |
5 | #include
6 |
7 | struct IFrameListener;
8 |
9 | struct IDirect3D9;
10 | struct IDirect3DDevice9;
11 | struct IDirect3DSurface9;
12 | struct IDirectXVideoProcessorService;
13 | struct IDirectXVideoProcessor;
14 |
15 | //class CD3DFont;
16 |
17 | class CPlayerDoc;
18 |
19 | //#define USE_DXVA2
20 |
21 | // CPlayerView view
22 |
23 | class CPlayerView : public CView, public IEraseableArea
24 | {
25 | friend class FrameListener;
26 |
27 | DECLARE_DYNCREATE(CPlayerView)
28 |
29 | protected:
30 | CPlayerView(); // protected constructor used by dynamic creation
31 | virtual ~CPlayerView();
32 |
33 | public:
34 | virtual void OnDraw(CDC* pDC); // overridden to draw this view
35 | #ifdef _DEBUG
36 | virtual void AssertValid() const;
37 | #ifndef _WIN32_WCE
38 | virtual void Dump(CDumpContext& dc) const;
39 | #endif
40 | #endif
41 |
42 | CPlayerDoc* GetDocument() const;
43 |
44 | void updateFrame();
45 |
46 | void OnErase(CWnd* pInitiator, CDC* pDC, BOOL isFullScreen) override;
47 |
48 | protected:
49 | DECLARE_MESSAGE_MAP()
50 | private:
51 | bool InitializeD3D9();
52 | bool InitializeExtra(bool createSurface);
53 | void DestroyExtra();
54 | void DestroyD3D9();
55 | #ifdef USE_DXVA2
56 | bool CreateDXVA2VPDevice(REFGUID guid, bool bDXVA2SW, bool createSurface);
57 | #endif
58 | bool ResetDevice();
59 | bool ProcessVideo();
60 |
61 | CRect GetScreenPosition(bool swapXY);
62 |
63 | private:
64 | std::unique_ptr m_frameListener;
65 | CSize m_sourceSize;
66 | CSize m_aspectRatio;
67 |
68 | CCriticalSection m_csSurface;
69 |
70 | CComPtr m_pD3D9;
71 | CComPtr m_pD3DD9;
72 | CComPtr m_pD3DRT;
73 | CComPtr m_pMainStream;
74 |
75 | bool m_bUseIMC3 = false;
76 |
77 | #ifdef USE_DXVA2
78 | CComPtr m_pDXVAVPS;
79 | CComPtr m_pDXVAVPD;
80 |
81 | LONG m_ProcAmpValues[4] {};
82 | LONG m_NFilterValues[6] {};
83 | LONG m_DFilterValues[6] {};
84 | #endif
85 |
86 | //std::unique_ptr m_subtitleFont;
87 |
88 | public:
89 | afx_msg void OnPaint();
90 | virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
91 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
92 | afx_msg BOOL OnEraseBkgnd(CDC* pDC);
93 | virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/);
94 | afx_msg void OnDropFiles(HDROP hDropInfo);
95 | afx_msg void OnEditPaste();
96 | afx_msg void OnEditCopy();
97 | };
98 |
--------------------------------------------------------------------------------
/Player/PlayerViewD2D.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include
5 |
6 | struct IFrameListener;
7 |
8 | struct ID2D1Effect;
9 |
10 | class CPlayerViewD2D : public CView
11 | {
12 | friend class FrameListenerD2D;
13 |
14 | protected: // create from serialization only
15 | CPlayerViewD2D();
16 | DECLARE_DYNCREATE(CPlayerViewD2D)
17 |
18 | // Attributes
19 | public:
20 | CPlayerDoc* GetDocument() const;
21 |
22 | // Operations
23 | public:
24 |
25 | // Overrides
26 | public:
27 | virtual void OnDraw(CDC* pDC); // overridden to draw this view
28 | virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
29 | protected:
30 | virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
31 | virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
32 | virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
33 |
34 | BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) override;
35 |
36 | // Implementation
37 | public:
38 | virtual ~CPlayerViewD2D();
39 | #ifdef _DEBUG
40 | virtual void AssertValid() const;
41 | virtual void Dump(CDumpContext& dc) const;
42 | #endif
43 |
44 | protected:
45 |
46 | private:
47 |
48 | // Generated message map functions
49 | protected:
50 | DECLARE_MESSAGE_MAP()
51 | afx_msg LRESULT OnDraw2D(WPARAM wParam, LPARAM lParam);
52 | afx_msg LRESULT DrawFrame(WPARAM wParam, LPARAM lParam);
53 | public:
54 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
55 | protected:
56 | void updateFrame();
57 |
58 | private:
59 | std::unique_ptr m_frameListener;
60 | CSize m_sourceSize;
61 | float m_aspectRatio;
62 | CComPtr m_spEffect;
63 |
64 | CCriticalSection m_csSurface;
65 |
66 | public:
67 | afx_msg void OnDropFiles(HDROP hDropInfo);
68 | afx_msg void OnEditPaste();
69 | };
70 |
--------------------------------------------------------------------------------
/Player/SecondsToString.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | inline std::basic_string secondsToString(int seconds, bool milli)
8 | {
9 | using std::setfill;
10 | using std::setw;
11 |
12 | std::basic_ostringstream buffer;
13 | if (seconds < (milli? 0 : -999))
14 | {
15 | buffer << '-';
16 | seconds = -seconds;
17 | }
18 | int ms = seconds % 1000;
19 | seconds /= 1000; // towards zero
20 | int s = seconds % 60;
21 | int m = (seconds / 60) % 60;
22 | int h = seconds / 3600;
23 |
24 | if (h > 0)
25 | {
26 | buffer << h << ':';
27 | }
28 | buffer << setfill(_T('0')) << setw(2) << m << ':' << setfill(_T('0')) << setw(2) << s;
29 | if (milli)
30 | {
31 | buffer << '.' << setfill(_T('0')) << setw(3) << ms;
32 | }
33 |
34 | return buffer.str();
35 | }
36 |
--------------------------------------------------------------------------------
/Player/StringDifference.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "StringDifference.h"
3 |
4 | #include
5 |
6 | static auto SafePathString(std::basic_string path)
7 | {
8 | enum
9 | {
10 | MAX_DIFF_SIZE = 2048
11 | };
12 | path.append(MAX_DIFF_SIZE, _T('\0'));
13 | return path;
14 | }
15 |
16 |
17 | template
18 | T reversed(const T& s)
19 | {
20 | return {s.rbegin(), s.rend()};
21 | }
22 |
23 | template
24 | int levenshteinDistance(const T& s1, const T& s2)
25 | {
26 | const int len1 = s1.size() + 1;
27 | const int len2 = s2.size() + 1;
28 | std::vector dp(len1 * len2);
29 |
30 | for (int i = 0; i < len1; ++i)
31 | {
32 | dp[i * len2] = i;
33 | }
34 | for (int j = 0; j < len2; ++j)
35 | {
36 | dp[j] = j;
37 | }
38 |
39 | for (int i = 1; i < len1; ++i)
40 | {
41 | for (int j = 1; j < len2; ++j)
42 | {
43 | const int cost = (s1[i - 1] != s2[j - 1]);
44 | dp[i * len2 + j] = (std::min)({dp[(i - 1) * len2 + j] + 1,
45 | dp[i * len2 + j - 1] + 1, dp[(i - 1) * len2 + j - 1] + cost});
46 | }
47 | }
48 |
49 | return dp.back();
50 | }
51 |
52 | StringDifference::StringDifference(const Sequence& a, const Sequence& b)
53 | : m_diff(a, b),
54 | m_reversedDiff(reversed(a), reversed(b)),
55 | m_path_b(b),
56 | m_sameNames(m_path_b.has_parent_path() && m_path_b.has_stem() &&
57 | m_path_b.stem() == std::filesystem::path(a).stem())
58 | {
59 | if (!m_sameNames)
60 | {
61 | m_diff.compose();
62 | m_reversedDiff.compose();
63 | }
64 | }
65 |
66 | StringDifference::Sequence StringDifference::patch(const Sequence& seq) const
67 | {
68 | if (m_sameNames)
69 | {
70 | return (m_path_b.parent_path() / std::filesystem::path(seq).stem()) +=
71 | m_path_b.extension();
72 | }
73 |
74 | Sequence s = m_reversedDiff.patch(SafePathString(reversed(seq)));
75 | std::reverse(s.begin(), s.begin() + _tcslen(s.c_str()));
76 | if (s.empty() || s[0] == 0 || 0 != _taccess(s.c_str(), 04))
77 | {
78 | s = m_diff.patch(SafePathString(seq));
79 | if (s.empty() || s[0] == 0 || 0 != _taccess(s.c_str(), 04))
80 | {
81 | auto closest = LastResort(seq);
82 | if (!closest.empty())
83 | return closest;
84 | }
85 | }
86 | s.resize(_tcslen(s.c_str()));
87 | return s;
88 | }
89 |
90 | StringDifference::Sequence StringDifference::LastResort(
91 | const StringDifference::Sequence& seq) const
92 | {
93 | try
94 | {
95 | const auto extension = m_path_b.extension();
96 | const Sequence name = std::filesystem::path(seq).stem();
97 | int minDistance = INT_MAX;
98 | std::filesystem::path result_name;
99 | for (auto const& dir_entry : std::filesystem::directory_iterator{m_path_b.parent_path()})
100 | {
101 | if (dir_entry.is_directory())
102 | continue;
103 | auto path = dir_entry.path();
104 | if (_tcsicmp(path.extension().c_str(), extension.c_str()) != 0)
105 | continue;
106 | const auto stem = path.stem();
107 | const int dist = levenshteinDistance(name, static_cast(stem));
108 | if (dist < minDistance)
109 | {
110 | minDistance = dist;
111 | result_name = stem;
112 | }
113 | else if (dist == minDistance)
114 | {
115 | result_name.clear();
116 | }
117 | }
118 | if (!result_name.empty())
119 | {
120 | auto result = (m_path_b.parent_path() / result_name) += extension;
121 | if (equivalent(m_path_b, result))
122 | return {};
123 | return result;
124 | }
125 | return {};
126 | }
127 | catch (const std::exception& ex)
128 | {
129 | TRACE("Exception in StringDifference: %s: %s\n", typeid(ex).name(), ex.what());
130 | return {};
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/Player/StringDifference.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // vcpkg install dtl
4 | #include
5 |
6 | #include
7 |
8 |
9 | class StringDifference
10 | {
11 | typedef std::basic_string Sequence;
12 |
13 | dtl::Diff> m_diff, m_reversedDiff;
14 | std::filesystem::path m_path_b;
15 | bool m_sameNames;
16 |
17 | Sequence LastResort(const StringDifference::Sequence& seq) const;
18 |
19 | public:
20 | StringDifference(const Sequence& a, const Sequence& b);
21 | Sequence patch(const Sequence& seq) const;
22 | };
23 |
--------------------------------------------------------------------------------
/Player/YouTuber.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | void CheckPython();
8 |
9 | std::vector ParsePlaylist(std::string url, bool force);
10 |
11 | std::vector ParsePlaylistFile(const TCHAR* fileName);
12 |
13 | std::vector ParsePlaylistText(const std::string& text);
14 |
15 | std::pair getYoutubeUrl(std::string url, bool adaptive, bool useSAN);
16 |
17 | // start, duration, text
18 | typedef std::function AddYoutubeTranscriptCallback;
19 |
20 | bool getYoutubeTranscripts(std::string url, AddYoutubeTranscriptCallback cb);
21 |
--------------------------------------------------------------------------------
/Player/res/Player.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/Player.ico
--------------------------------------------------------------------------------
/Player/res/Player.rc2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/Player.rc2
--------------------------------------------------------------------------------
/Player/res/PlayerDoc.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/PlayerDoc.ico
--------------------------------------------------------------------------------
/Player/res/Toolbar.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/Toolbar.bmp
--------------------------------------------------------------------------------
/Player/res/audio.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/audio.ico
--------------------------------------------------------------------------------
/Player/res/audio_off.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/audio_off.ico
--------------------------------------------------------------------------------
/Player/res/full_screen.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/full_screen.ico
--------------------------------------------------------------------------------
/Player/res/launch.mkv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/launch.mkv
--------------------------------------------------------------------------------
/Player/res/pause.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/pause.ico
--------------------------------------------------------------------------------
/Player/res/play.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Player/res/play.ico
--------------------------------------------------------------------------------
/Player/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by Player.rc
4 | //
5 | #define IDD_ABOUTBOX 100
6 | #define IDD_DIALOGBAR_PLAYER_CONTROL 103
7 | #define ID_VIEW_CUSTOMIZE 126
8 | #define IDR_MAINFRAME 128
9 | #define IDS_TOOLBAR_CUSTOMIZE 129
10 | #define IDR_PlayerTYPE 130
11 | #define IDS_PlayerControl 130
12 | #define IDS_PLAYER_CONTROL 130
13 | #define IDS_RANGE 131
14 | #define IDS_PAUSE 132
15 | #define IDS_PLAY 133
16 | #define IDI_PAUSE 311
17 | #define IDI_PLAY 312
18 | #define IDI_AUDIO 313
19 | #define IDI_AUDIO_OFF 314
20 | #define IDI_FULL_SCREEN 315
21 | #define IDD_DIALOG_OPEN_URL 317
22 | #define IDD_DIALOGBAR_RANGE 319
23 | #define IDR_LAUNCH 320
24 | #define IDC_PROGRESS_SLIDER 1000
25 | #define IDC_PLAY_PAUSE 1001
26 | #define IDC_AUDIO_ON_OFF 1002
27 | #define IDC_VOLUME_SLIDER 1003
28 | #define IDC_CURRENT_TIME 1004
29 | #define IDC_TOTAL_TIME 1005
30 | #define IDC_EDIT_URL 1005
31 | #define IDC_FULL_SCREEN 1006
32 | #define IDC_FRAME_STEP 1007
33 | #define IDC_START 1008
34 | #define IDC_EDIT_START 1010
35 | #define IDC_START_RESET 1011
36 | #define IDC_END 1012
37 | #define IDC_EDIT_END 1013
38 | #define IDC_END_RESET 1014
39 | #define IDC_PARSE 1016
40 | #define IDC_VIDEO_PROPERTIES 1017
41 | #define IDC_APP_NAME_VERSION 1018
42 | #define IDC_EDIT_INPUT_FORMAT 1019
43 | #define IDC_LOSSLESS_CUT 1020
44 | #define ID_TRACK1_DUMMY 32771
45 | #define ID_AUTOPLAY 32775
46 | #define ID_LOOPING 32776
47 | #define ID_VIDEO_SPEED1 32777
48 | #define ID_VIDEO_SPEED2 32778
49 | #define ID_VIDEO_SPEED3 32779
50 | #define ID_VIDEO_SPEED4 32780
51 | #define ID_VIDEO_SPEED5 32781
52 | #define ID_VIDEO_SPEED6 32782
53 | #define ID_VIDEO_SPEED7 32783
54 | #define ID_NIGHTCORE 32784
55 | #define ID_OPENSUBTITLESFILE 32785
56 | #define ID_COPY_URL_TO_CLIPBOARD 32786
57 | #define ID_MAXIMALRESOLUTION 32787
58 | #define ID_HW_ACCELERATION 32788
59 | #define ID_AUDIO_OPENSUBTITLES 32789
60 | #define ID_FIRST_SUBTITLE_DUMMY 32790
61 | #define ID_SUPER_RESOLUTION 32791
62 | #define ID_ORIENTATION_MIRRORX 32792
63 | #define ID_ORIENTATION_MIRRORY 32793
64 | #define ID_ORIENTATION_UPEND 32794
65 | #define ID_ORIENTATION_DO_NOTHING 32795
66 | #define ID_ORIENTATION_RORATE_90 32796
67 | #define ID_ORIENTATION_RORATE_180 32797
68 | #define ID_ORIENTATION_RORATE_270 32798
69 | #define ID_FIX_ENCODING 32799
70 | #define ID_CONVERT_VIDEOS_INTO_COMPATIBLE_FORMAT 32800
71 | #define ID_OPEN_AUDIO_FILE 32801
72 | #define ID_USING_SAN_CERTIFICATE 32802
73 |
74 | // Next default values for new objects
75 | //
76 | #ifdef APSTUDIO_INVOKED
77 | #ifndef APSTUDIO_READONLY_SYMBOLS
78 | #define _APS_NEXT_RESOURCE_VALUE 321
79 | #define _APS_NEXT_COMMAND_VALUE 32803
80 | #define _APS_NEXT_CONTROL_VALUE 1021
81 | #define _APS_NEXT_SYMED_VALUE 310
82 | #endif
83 | #endif
84 |
--------------------------------------------------------------------------------
/Player/stdafx.cpp:
--------------------------------------------------------------------------------
1 |
2 | // stdafx.cpp : source file that includes just the standard includes
3 | // Player.pch will be the pre-compiled header
4 | // stdafx.obj will contain the pre-compiled type information
5 |
6 | #include "stdafx.h"
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Player/stdafx.h:
--------------------------------------------------------------------------------
1 |
2 | // stdafx.h : include file for standard system include files,
3 | // or project specific include files that are used frequently,
4 | // but are changed infrequently
5 |
6 | #pragma once
7 |
8 | #ifndef VC_EXTRALEAN
9 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
10 | #endif
11 |
12 | #include "targetver.h"
13 |
14 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
15 |
16 | // turns off MFC's hiding of some common and often safely ignored warning messages
17 | #define _AFX_ALL_WARNINGS
18 |
19 | #include // MFC core and standard components
20 | #include // MFC extensions
21 |
22 |
23 |
24 |
25 |
26 | #ifndef _AFX_NO_OLE_SUPPORT
27 | #include // MFC support for Internet Explorer 4 Common Controls
28 | #endif
29 | #ifndef _AFX_NO_AFXCMN_SUPPORT
30 | #include // MFC support for Windows Common Controls
31 | #endif // _AFX_NO_AFXCMN_SUPPORT
32 |
33 | #include // MFC support for ribbons and control bars
34 |
35 |
36 |
37 | #ifdef _UNICODE
38 | #if defined _M_IX86
39 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
40 | #elif defined _M_X64
41 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
42 | #else
43 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
44 | #endif
45 | #endif
46 |
--------------------------------------------------------------------------------
/Player/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
10 | #define _WIN32_WINNT _WIN32_WINNT_WIN8
11 | #define NTDDI_VERSION NTDDI_WIN8
12 | #define WINVER _WIN32_WINNT_WIN8
13 | #define _WIN32_IE _WIN32_IE_WIN8
14 |
15 | #include
16 |
--------------------------------------------------------------------------------
/Player/update_version.cmd:
--------------------------------------------------------------------------------
1 | %~dp0\version.h.tmp
2 | git --work-tree=%~dp0 rev-parse --short HEAD >> %~dp0\version.h.tmp
3 | if %ERRORLEVEL% neq 0 echo #define NO_GIT_COMMIT > %~dp0\version.h.tmp
4 | fc %~dp0\version.h.tmp %~dp0\version.h
5 | if %ERRORLEVEL% neq 0 copy /Y %~dp0\version.h.tmp %~dp0\version.h
6 | del %~dp0\version.h.tmp
7 |
--------------------------------------------------------------------------------
/QtPlayer/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/QtPlayer/.gitignore:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 | *.slo
3 | *.lo
4 | *.o
5 | *.a
6 | *.la
7 | *.lai
8 | *.so
9 | *.dll
10 | *.dylib
11 |
12 | # Qt-es
13 | object_script.*.Release
14 | object_script.*.Debug
15 | *_plugin_import.cpp
16 | /.qmake.cache
17 | /.qmake.stash
18 | *.pro.user
19 | *.pro.user.*
20 | *.qbs.user
21 | *.qbs.user.*
22 | *.moc
23 | moc_*.cpp
24 | moc_*.h
25 | qrc_*.cpp
26 | ui_*.h
27 | *.qmlc
28 | *.jsc
29 | Makefile*
30 | *build-*
31 |
32 | # Qt unit tests
33 | target_wrapper.*
34 |
35 | # QtCreator
36 | *.autosave
37 |
38 | # QtCreator Qml
39 | *.qmlproject.user
40 | *.qmlproject.user.*
41 |
42 | # QtCreator CMake
43 | CMakeLists.txt.user*
44 | CMake*Presets.json
45 |
--------------------------------------------------------------------------------
/QtPlayer/customdockwidget.cpp:
--------------------------------------------------------------------------------
1 | #include "customdockwidget.h"
2 | #include "mainwindow.h"
3 | #include "videoplayerwidget.h"
4 | #include "videowidget.h"
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | CustomDockWidget::CustomDockWidget(QWidget* widget) : QWidget(widget)
11 | {
12 | }
13 |
14 | void CustomDockWidget::setDisplayForFullscreen(VideoDisplay* display)
15 | {
16 | Q_ASSERT(display != nullptr);
17 | m_display = dynamic_cast(display);
18 | }
19 |
20 | void CustomDockWidget::closeEvent(QCloseEvent* event)
21 | {
22 | event->ignore();
23 | }
24 |
25 | void CustomDockWidget::keyPressEvent(QKeyEvent* event)
26 | {
27 | // Player fullscreen in
28 | if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && (event->modifiers() & Qt::AltModifier))
29 | {
30 | setVisibilityState(FullScreen);
31 | event->ignore();
32 | }
33 | QWidget::keyPressEvent(event);
34 | }
35 |
36 | void CustomDockWidget::setVisibilityState(VisibilityState state)
37 | {
38 | if (state == m_state)
39 | {
40 | return;
41 | }
42 |
43 | switch (state)
44 | {
45 | case ShownDocked:
46 | {
47 | this->setVisible(true);
48 | }
49 | break;
50 | case FullScreen:
51 | {
52 | bool prevIsFullScreen = m_display->isFullScreen();
53 | m_display->fullScreen(!prevIsFullScreen);
54 | if (m_display->isFullScreen() == prevIsFullScreen)
55 | {
56 | return;
57 | }
58 | // emit enterFullscreen(true);
59 | }
60 | break;
61 | }
62 | m_prevState = m_state;
63 | m_state = state;
64 | }
65 |
66 | void CustomDockWidget::onLeaveFullScreen()
67 | {
68 | if (m_display->isFullScreen())
69 | {
70 | m_display->fullScreen(false);
71 | }
72 | setVisibilityState(m_prevState);
73 | }
74 |
--------------------------------------------------------------------------------
/QtPlayer/customdockwidget.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class VideoDisplay;
6 | class VideoWidget;
7 |
8 |
9 | class CustomDockWidget : public QWidget
10 | {
11 | Q_OBJECT
12 | public:
13 | CustomDockWidget(QWidget* widget = nullptr);
14 | void setDisplayForFullscreen(VideoDisplay* display);
15 |
16 | enum VisibilityState
17 | {
18 | ShownDocked = 0,
19 | FullScreen
20 | };
21 |
22 | void setVisibilityState(VisibilityState state);
23 | VisibilityState currentState() const { return m_state; }
24 | VisibilityState previousState() const { return m_prevState; }
25 |
26 | protected:
27 | void closeEvent(QCloseEvent* event) override;
28 | void keyPressEvent(QKeyEvent* event) override;
29 |
30 | signals:
31 | bool enterFullscreen(bool f);
32 |
33 | public slots:
34 | void onLeaveFullScreen();
35 |
36 | private:
37 | VisibilityState m_state{ShownDocked};
38 | VisibilityState m_prevState{ShownDocked};
39 | VideoWidget* m_display{};
40 | };
41 |
--------------------------------------------------------------------------------
/QtPlayer/ffmpegdecoder.cpp:
--------------------------------------------------------------------------------
1 | #include "ffmpegdecoder.h"
2 |
3 | //#include "../audio/AudioPlayerWasapi.h"
4 |
5 | #include "portaudioplayer.h"
6 |
7 | #include "videodisplay.h"
8 |
9 | FFmpegDecoderWrapper::FFmpegDecoderWrapper()
10 | : m_frameDecoder(
11 | GetFrameDecoder(std::make_unique()))
12 | {
13 | m_frameDecoder->setDecoderListener(this);
14 | }
15 |
16 | FFmpegDecoderWrapper::~FFmpegDecoderWrapper() = default;
17 |
18 | void FFmpegDecoderWrapper::setFrameListener(VideoDisplay* listener)
19 | {
20 | m_frameDecoder->setFrameListener(listener);
21 | if (listener != nullptr) {
22 | listener->setDecoderObject(this);
23 | }
24 | }
25 |
26 | bool FFmpegDecoderWrapper::openFile(const QString& file)
27 | {
28 | return m_frameDecoder->openUrls({file.toStdString()});
29 | }
30 |
--------------------------------------------------------------------------------
/QtPlayer/ffmpegdecoder.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../video/decoderinterface.h"
4 |
5 | #include
6 |
7 | #include
8 |
9 | #include
10 |
11 | class VideoDisplay;
12 |
13 | class FFmpegDecoderWrapper : public QObject, public FrameDecoderListener
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | FFmpegDecoderWrapper();
19 | ~FFmpegDecoderWrapper() override;
20 |
21 | FFmpegDecoderWrapper(const FFmpegDecoderWrapper&) = delete;
22 | FFmpegDecoderWrapper& operator=(const FFmpegDecoderWrapper&) = delete;
23 |
24 | void setFrameListener(VideoDisplay* listener);
25 |
26 | bool openFile(const QString& file);
27 | void play(bool isPaused = false) { m_frameDecoder->play(); }
28 | bool pauseResume() { return m_frameDecoder->pauseResume(); }
29 | void close(bool isBlocking = true) { m_frameDecoder->close(); }
30 | void setVolume(double volume)
31 | {
32 | m_frameDecoder->setVolume(volume);
33 | emit volumeChanged(volume);
34 | }
35 | bool seekByPercent(float percent) { return m_frameDecoder->seekByPercent(percent); }
36 |
37 | double volume() const { return m_frameDecoder->volume(); }
38 | bool isPlaying() const { return m_frameDecoder->isPlaying(); }
39 |
40 | void finishedDisplayingFrame(unsigned int generation) { m_frameDecoder->finishedDisplayingFrame(generation); }
41 |
42 | IFrameDecoder* getFrameDecoder() const { return m_frameDecoder.get(); }
43 |
44 | void playingFinished() override { emit onPlayingFinished(); }
45 | void changedFramePosition(
46 | long long start, long long frame, long long total) override
47 | {
48 | emit onChangedFramePosition(frame - start, total - start);
49 | }
50 |
51 | signals:
52 | void onPlayingFinished();
53 | void onChangedFramePosition(qint64, qint64);
54 | void volumeChanged(double /*unused*/) override;
55 |
56 | private:
57 | std::unique_ptr m_frameDecoder;
58 | };
59 |
--------------------------------------------------------------------------------
/QtPlayer/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include
14 |
15 | #include
16 |
17 | static void init_logging()
18 | {
19 | namespace expr = boost::log::expressions;
20 |
21 | boost::log::add_common_attributes();
22 |
23 | auto core = boost::log::core::get();
24 |
25 | #ifdef Q_OS_WIN
26 | // Create the sink. The backend requires synchronization in the frontend.
27 | auto sink(boost::make_shared>());
28 | #else
29 | auto sink = boost::make_shared>();
30 | #endif
31 |
32 | sink->set_formatter(expr::stream
33 | //<< '[' << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%H:%M:%S.%f") << ']'
34 | << expr::if_(expr::has_attr("Severity"))
35 | [
36 | expr::stream << '[' << expr::attr< boost::log::trivial::severity_level >("Severity") << ']'
37 | ]
38 | << expr::if_(expr::has_attr("Channel"))
39 | [
40 | expr::stream << '[' << expr::attr< std::string >("Channel") << ']'
41 | ]
42 | << expr::smessage << '\n');
43 |
44 | // Set the special filter to the frontend
45 | // in order to skip the sink when no debugger is available
46 | //sink->set_filter(expr::is_debugger_present());
47 |
48 | core->add_sink(sink);
49 | }
50 |
51 | int main(int argc, char *argv[])
52 | {
53 | init_logging();
54 |
55 | QApplication a(argc, argv);
56 | MainWindow w;
57 | w.show();
58 | return QApplication::exec();
59 | }
60 |
--------------------------------------------------------------------------------
/QtPlayer/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include "./ui_mainwindow.h"
3 |
4 | #include "videowidget.h"
5 |
6 | #include
7 | #include
8 |
9 | MainWindow* getMainWindow()
10 | {
11 | for (QWidget* widget : QApplication::topLevelWidgets()) {
12 | if (auto *mainWindow = qobject_cast(widget)) {
13 | return mainWindow;
14 | }
15 | }
16 | return nullptr;
17 | }
18 |
19 |
20 | MainWindow::MainWindow(QWidget *parent)
21 | : QMainWindow(parent)
22 | , ui(new Ui::MainWindow)
23 | {
24 | ui->setupUi(this);
25 |
26 | auto m_player = ui->videoPlayerWidget;
27 |
28 | m_player->setProgressbar(ui->videoProgress);
29 |
30 | ui->dockWidget->installEventFilter(m_player);
31 | ui->dockWidget->setDisplayForFullscreen(m_player->getCurrentDisplay());
32 |
33 | setCentralWidget(ui->dockWidget);
34 |
35 | connect(m_player->videoWidget(), &VideoWidget::leaveFullScreen, ui->dockWidget, &CustomDockWidget::onLeaveFullScreen);
36 |
37 | connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::onFileOpen);
38 | connect(ui->actionOpenUrl, &QAction::triggered, this, &MainWindow::onUrlOpen);
39 | }
40 |
41 | MainWindow::~MainWindow()
42 | {
43 | delete ui;
44 | }
45 |
46 | CustomDockWidget* MainWindow::dockWidget()
47 | {
48 | return ui->dockWidget;
49 | }
50 |
51 | QWidget* MainWindow::videoControlWidget()
52 | {
53 | return ui->videoControl;
54 | }
55 |
56 | VideoPlayerWidget* MainWindow::getPlayer()
57 | {
58 | return ui->videoPlayerWidget;
59 | }
60 |
61 | void MainWindow::onFileOpen()
62 | {
63 | auto fileName = QFileDialog::getOpenFileName(
64 | this,
65 | tr("Open Video File"));
66 | if (!fileName.isEmpty())
67 | {
68 | getPlayer()->playFile(fileName);
69 | }
70 | }
71 |
72 | void MainWindow::onUrlOpen()
73 | {
74 | QInputDialog dialog(this);
75 | dialog.setWindowTitle(tr("Open URL"));
76 | dialog.setLabelText(tr("Url to open:"));
77 | if (dialog.exec() == QDialog::Accepted)
78 | {
79 | QString fileName = dialog.textValue();
80 | if (!fileName.isEmpty())
81 | {
82 | getPlayer()->playFile(fileName);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/QtPlayer/mainwindow.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | QT_BEGIN_NAMESPACE
6 | namespace Ui { class MainWindow; }
7 | QT_END_NAMESPACE
8 |
9 | class CustomDockWidget;
10 | class VideoPlayerWidget;
11 |
12 | class MainWindow : public QMainWindow
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | MainWindow(QWidget *parent = nullptr);
18 | ~MainWindow() override;
19 |
20 |
21 | CustomDockWidget* dockWidget();
22 | QWidget* videoControlWidget();
23 | VideoPlayerWidget* getPlayer();
24 |
25 | private:
26 | void onFileOpen();
27 | void onUrlOpen();
28 |
29 | private:
30 | Ui::MainWindow *ui;
31 | };
32 |
33 | MainWindow* getMainWindow();
34 |
--------------------------------------------------------------------------------
/QtPlayer/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 803
10 | 604
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 |
19 | 0
20 | 0
21 |
22 |
23 |
24 |
25 | 16777215
26 | 16777215
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 0
35 |
36 |
37 | 0
38 |
39 | -
40 |
41 |
42 | Qt::StrongFocus
43 |
44 |
45 |
46 |
47 |
48 | QFrame::NoFrame
49 |
50 |
51 | QFrame::Plain
52 |
53 |
54 | 0
55 |
56 |
57 |
58 |
59 | 0
60 | 238
61 | 230
62 | 16
63 |
64 |
65 |
66 |
67 |
68 |
69 | 0
70 | 220
71 | 229
72 | 18
73 |
74 |
75 |
76 |
77 | 16777215
78 | 18
79 |
80 |
81 |
82 |
83 |
84 |
85 | 10000
86 |
87 |
88 | 0
89 |
90 |
91 | false
92 |
93 |
94 |
95 |
96 |
97 |
98 |
116 |
117 |
118 |
119 | Open
120 |
121 |
122 |
123 |
124 | Open URL
125 |
126 |
127 |
128 |
129 |
130 | VideoControl
131 | QWidget
132 |
133 | 1
134 |
135 |
136 | CustomDockWidget
137 | QWidget
138 |
139 | 1
140 |
141 |
142 | VideoPlayerWidget
143 | QFrame
144 |
145 | 1
146 |
147 |
148 | VideoProgressBar
149 | QProgressBar
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/QtPlayer/mousehoverbutton.cpp:
--------------------------------------------------------------------------------
1 | #include "mousehoverbutton.h"
2 | #include
3 |
4 | MouseHoverButton::MouseHoverButton(QWidget* parent) : QToolButton(parent)
5 | {
6 | }
7 |
8 |
9 | MouseHoverButton::~MouseHoverButton() = default;
10 |
11 | void MouseHoverButton::mousePressEvent(QMouseEvent* event)
12 | {
13 | if (m_defIcon.isNull())
14 | {
15 | m_defIcon = icon();
16 | QList normalOnSizes = m_defIcon.availableSizes(QIcon::Normal, QIcon::On);
17 | if (!normalOnSizes.empty())
18 | {
19 | // use normal/on image as pushed one
20 | m_pushedIcon = m_defIcon.pixmap(*normalOnSizes.begin(), QIcon::Normal, QIcon::On);
21 | }
22 | }
23 | QToolButton::mousePressEvent(event);
24 | if (event->buttons() & Qt::LeftButton)
25 | {
26 | setIcon(m_pushedIcon);
27 | }
28 | }
29 |
30 | void MouseHoverButton::mouseReleaseEvent(QMouseEvent* event)
31 | {
32 | if (event->button() == Qt::LeftButton)
33 | {
34 | setIcon(m_defIcon);
35 | }
36 | QToolButton::mouseReleaseEvent(event);
37 | }
38 |
39 | void MouseHoverButton::keyReleaseEvent(QKeyEvent* e)
40 | {
41 | Q_UNUSED(e)
42 | // do nothing so button won't process key events
43 | }
44 |
45 | void MouseHoverButton::paintEvent(QPaintEvent* event)
46 | {
47 | bool isButtonDown = isDown();
48 | setDown(false);
49 | QToolButton::paintEvent(event);
50 | setDown(isButtonDown);
51 | }
52 |
--------------------------------------------------------------------------------
/QtPlayer/mousehoverbutton.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | /*
7 | Since Qt tool button pushes icon's image for pressed state, we have own implementation.
8 | To get it properly worked next images should be assigned to
9 | next button states programmatically or in the Qt designer:
10 | Normal Off - default image
11 | Normal On - clicked image
12 | Disabled Off - disabled image
13 | Disabled On - disabled image
14 | Active Off - hover image
15 | Active On - hover image
16 | Selected Off - default image
17 | Selected On - default image
18 | */
19 | class MouseHoverButton : public QToolButton
20 | {
21 | Q_OBJECT
22 | public:
23 | MouseHoverButton(QWidget* parent);
24 | ~MouseHoverButton() override;
25 | protected:
26 | void mousePressEvent(QMouseEvent* event) override;
27 | void mouseReleaseEvent(QMouseEvent* event) override;
28 | void keyReleaseEvent(QKeyEvent* e) override;
29 | void paintEvent(QPaintEvent* event) override;
30 | private:
31 | QIcon m_defIcon;
32 | QIcon m_pushedIcon;
33 | };
34 |
--------------------------------------------------------------------------------
/QtPlayer/opengldisplay.h:
--------------------------------------------------------------------------------
1 | #ifndef OPENGLDISPLAY_H
2 | #define OPENGLDISPLAY_H
3 |
4 | // https://github.com/MasterAler/SampleYUVRenderer
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "videodisplay.h"
12 |
13 | class OpenGLDisplay : public QOpenGLWidget, public QOpenGLFunctions, public VideoDisplay
14 | {
15 | Q_OBJECT
16 | public:
17 | explicit OpenGLDisplay(QWidget* parent = nullptr);
18 | ~OpenGLDisplay() override;
19 |
20 | void InitDrawBuffer(unsigned bsize);
21 |
22 | void showPicture(const QImage& img) override;
23 | void showPicture(const QPixmap& picture) override;
24 |
25 | // decoder->finishedDisplayingFrame() must be called
26 | void updateFrame(IFrameDecoder* decoder, unsigned int generation) override;
27 | void drawFrame(IFrameDecoder* decoder, unsigned int generation) override;
28 | void decoderClosing() override;
29 |
30 | float aspectRatio() const;
31 |
32 | protected:
33 | void initializeGL() override;
34 | void paintGL() override;
35 |
36 | private:
37 | struct OpenGLDisplayImpl;
38 | QScopedPointer impl;
39 | };
40 |
41 | /***********************************************************************/
42 |
43 | class OpenGlException: public QException
44 | {
45 | public:
46 | void raise() const override { throw *this; }
47 | OpenGlException *clone() const override { return new OpenGlException(*this); }
48 | };
49 |
50 | #endif // OPENGLDISPLAY_H
51 |
--------------------------------------------------------------------------------
/QtPlayer/portaudioplayer.cpp:
--------------------------------------------------------------------------------
1 | #include "portaudioplayer.h"
2 |
3 | #include
4 | #include
5 |
6 | PortAudioPlayer::PortAudioPlayer()
7 | {
8 | auto err = Pa_Initialize();
9 | }
10 |
11 | PortAudioPlayer::~PortAudioPlayer()
12 | {
13 | auto err = Pa_Terminate();
14 | }
15 |
16 | void PortAudioPlayer::InitializeThread()
17 | {
18 | QThread::currentThread()->setPriority(QThread::TimeCriticalPriority);
19 | }
20 |
21 | bool PortAudioPlayer::Open(int bytesPerSample, int channels, int* samplesPerSec)
22 | {
23 | PaStreamParameters params{};
24 | params.device = Pa_GetDefaultOutputDevice();
25 | params.suggestedLatency = Pa_GetDeviceInfo(params.device)->defaultLowOutputLatency;
26 | params.channelCount = channels;
27 |
28 | switch (bytesPerSample)
29 | {
30 | case 1:
31 | params.sampleFormat = paInt8;
32 | break;
33 | case 2:
34 | params.sampleFormat = paInt16;
35 | break;
36 | case 4:
37 | params.sampleFormat = paInt32;
38 | break;
39 | }
40 |
41 | auto err{ Pa_OpenStream(&m_stream, nullptr, ¶ms, *samplesPerSec, paFramesPerBufferUnspecified,
42 | paNoFlag, nullptr, nullptr) };
43 |
44 | if (err != paNoError) {
45 | return false;
46 | }
47 |
48 | err = Pa_StartStream(m_stream);
49 |
50 | m_FrameSize = bytesPerSample * channels;
51 |
52 | *samplesPerSec = m_samplesPerSec = Pa_GetStreamInfo(m_stream)->sampleRate;
53 |
54 | return true;
55 | }
56 |
57 | void PortAudioPlayer::Close()
58 | {
59 | auto err = Pa_CloseStream(m_stream);
60 | m_stream = nullptr;
61 | }
62 |
63 | bool PortAudioPlayer::WriteAudio(uint8_t* write_data, int64_t write_size)
64 | {
65 | if (!m_stream) {
66 | return false;
67 | }
68 |
69 | auto* realData = (int16_t*)write_data;
70 | for (unsigned int i = 0; i < write_size / 2; ++i) {
71 | realData[i] *= m_volume;
72 | }
73 |
74 | const auto framesToWrite = write_size / m_FrameSize;
75 | auto err = Pa_WriteStream(m_stream, write_data, framesToWrite);
76 | if (err == paStreamIsStopped && Pa_StartStream(m_stream) == paNoError)
77 | {
78 | err = Pa_WriteStream(m_stream, write_data, framesToWrite);
79 | }
80 |
81 | // count audio pts
82 | const double frame_clock = (double)framesToWrite / m_samplesPerSec;
83 | m_callback->AppendFrameClock(frame_clock);
84 |
85 | return err == paNoError;
86 | }
87 |
88 | void PortAudioPlayer::WaveOutReset()
89 | {
90 | Pa_AbortStream(m_stream);
91 | }
92 |
93 | void PortAudioPlayer::WaveOutPause()
94 | {
95 | Pa_StopStream(m_stream);
96 | }
97 |
98 | void PortAudioPlayer::WaveOutRestart()
99 | {
100 | Pa_StartStream(m_stream);
101 | }
102 |
--------------------------------------------------------------------------------
/QtPlayer/portaudioplayer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../video/audioplayer.h"
4 |
5 |
6 | class PortAudioPlayer :
7 | public IAudioPlayer
8 | {
9 | public:
10 | PortAudioPlayer();
11 | ~PortAudioPlayer() override;
12 |
13 | PortAudioPlayer(const PortAudioPlayer&) = delete;
14 | PortAudioPlayer& operator=(const PortAudioPlayer&) = delete;
15 |
16 | void SetCallback(IAudioPlayerCallback* callback) override
17 | {
18 | m_callback = callback;
19 | }
20 |
21 | void InitializeThread() override;
22 | void DeinitializeThread() override {}
23 |
24 | void WaveOutReset() override;
25 |
26 | void Close() override;
27 | bool Open(int bytesPerSample, int channels, int* samplesPerSec) override;
28 |
29 | void SetVolume(double volume) override { m_volume = volume; }
30 | double GetVolume() const override { return m_volume; }
31 |
32 | void WaveOutPause() override;
33 | void WaveOutRestart() override;
34 |
35 | bool WriteAudio(uint8_t* write_data, int64_t write_size) override;
36 |
37 | private:
38 | IAudioPlayerCallback* m_callback{};
39 | void* m_stream{};
40 |
41 | int m_FrameSize{};
42 | double m_samplesPerSec{};
43 | double m_volume = 1.;
44 | };
45 |
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/icodelete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/icodelete.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/icoplay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/icoplay.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_globe___click___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_globe___click___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_globe___default___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_globe___default___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_globe___hover___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_globe___hover___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_pause___clicked___(40x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_pause___clicked___(40x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_pause___default___(40x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_pause___default___(40x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_pause___hover___(40x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_pause___hover___(40x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_play___clicked___(40x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_play___clicked___(40x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_play___default___(40x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_play___default___(40x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_play___hover___(40x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_play___hover___(40x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_sound_off___clicked___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_sound_off___clicked___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_sound_off___default___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_sound_off___default___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_sound_off___hover___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_sound_off___hover___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_sound_on___clicked___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_sound_on___clicked___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_sound_on___default___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_sound_on___default___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_sound_on___hover___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_sound_on___hover___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_stop___clicked___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_stop___clicked___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_stop___default___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_stop___default___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player___btn_stop___hover___(31x31).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player___btn_stop___hover___(31x31).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player_bg___(230x41).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player_bg___(230x41).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/control/player_bg_fs___(230x41).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/control/player_bg_fs___(230x41).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/help41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/help41.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/play_transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/play_transparent.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/spinner.gif
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/box-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/box-shadow.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/busy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/busy.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/button-blank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/button-blank.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/button_disable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/button_disable.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/button_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/button_down.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/button_hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/button_hover.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/button_normal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/button_normal.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/circle-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/circle-shadow.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/down_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/down_arrow.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/down_arrow_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/down_arrow_grey.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/floatpanel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/floatpanel.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/header_arrow_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/header_arrow_down.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/header_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/header_line.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/lineedit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/lineedit.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/progress_dropdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/progress_dropdown.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-button-down-hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-button-down-hover.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-button-down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-button-down.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-button-left-hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-button-left-hover.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-button-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-button-left.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-button-right-hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-button-right-hover.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-button-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-button-right.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-button-up-hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-button-up-hover.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-button-up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-button-up.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-hhandle-hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-hhandle-hover.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-hhandle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-hhandle.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-vhandle-hover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-vhandle-hover.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/scroll-vhandle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/scroll-vhandle.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/style/tooltip-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/style/tooltip-background.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/triangle_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/triangle_down.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/triangle_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/triangle_right.png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/video___btn_play___clicked___(94x94).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/video___btn_play___clicked___(94x94).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/video___btn_play___default___(94x94).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/video___btn_play___default___(94x94).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/video___btn_play___hover___(94x94).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/video___btn_play___hover___(94x94).png
--------------------------------------------------------------------------------
/QtPlayer/resources/images/video_seek_cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/QtPlayer/resources/images/video_seek_cursor.png
--------------------------------------------------------------------------------
/QtPlayer/resources/qt.conf:
--------------------------------------------------------------------------------
1 | [Paths]
2 | Plugins = .
--------------------------------------------------------------------------------
/QtPlayer/resources/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | style.css
4 | images/help41.png
5 | images/style/button_disable.png
6 | images/style/button_down.png
7 | images/style/button_hover.png
8 | images/style/button_normal.png
9 | images/style/header_arrow_down.png
10 | images/style/down_arrow.png
11 | images/style/lineedit.png
12 | images/style/down_arrow_grey.png
13 | images/play_transparent.png
14 | images/video___btn_play___default___(94x94).png
15 | images/video___btn_play___hover___(94x94).png
16 | images/video___btn_play___clicked___(94x94).png
17 | images/style/box-shadow.png
18 | images/style/busy.png
19 | images/style/button-blank.png
20 | images/style/floatpanel.png
21 | images/spinner.gif
22 | images/triangle_down.png
23 | images/triangle_right.png
24 | images/style/progress_dropdown.png
25 | images/style/circle-shadow.png
26 | images/style/tooltip-background.png
27 | images/video_seek_cursor.png
28 |
29 |
30 | images/style/header_line.png
31 | images/style/scroll-button-down.png
32 | images/style/scroll-button-down-hover.png
33 | images/style/scroll-button-up.png
34 | images/style/scroll-button-up-hover.png
35 | images/style/scroll-vhandle.png
36 | images/style/scroll-vhandle-hover.png
37 | images/style/scroll-button-left.png
38 | images/style/scroll-button-left-hover.png
39 | images/style/scroll-button-right.png
40 | images/style/scroll-button-right-hover.png
41 | images/style/scroll-hhandle.png
42 | images/style/scroll-hhandle-hover.png
43 |
44 |
45 | images/control/player_bg___(230x41).png
46 | images/control/player_bg_fs___(230x41).png
47 | images/control/player___btn_play___default___(40x31).png
48 | images/control/player___btn_play___clicked___(40x31).png
49 | images/control/player___btn_play___hover___(40x31).png
50 | images/control/player___btn_stop___default___(31x31).png
51 | images/control/player___btn_stop___clicked___(31x31).png
52 | images/control/player___btn_stop___hover___(31x31).png
53 | images/control/player___btn_globe___default___(31x31).png
54 | images/control/player___btn_globe___click___(31x31).png
55 | images/control/player___btn_globe___hover___(31x31).png
56 | images/control/player___btn_sound_on___default___(31x31).png
57 | images/control/player___btn_sound_on___clicked___(31x31).png
58 | images/control/player___btn_sound_on___hover___(31x31).png
59 | images/control/player___btn_sound_off___default___(31x31).png
60 | images/control/player___btn_sound_off___clicked___(31x31).png
61 | images/control/player___btn_sound_off___hover___(31x31).png
62 | images/control/player___btn_pause___default___(40x31).png
63 | images/control/player___btn_pause___clicked___(40x31).png
64 | images/control/player___btn_pause___hover___(40x31).png
65 | images/control/icodelete.png
66 | images/control/icoplay.png
67 |
68 |
69 |
--------------------------------------------------------------------------------
/QtPlayer/resources/win7.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/QtPlayer/resources/winres.rc.in:
--------------------------------------------------------------------------------
1 | #include "verrsrc.h"
2 |
3 | IDI_ICON1 ICON "@ICON_FILE@"
4 |
5 | #define VER_FILEVERSION @MAJOR_VER@,@MINOR_VER1@,@MINOR_VER2@,@MINOR_VER3@
6 | #define VER_FILEVERSION_STR "@MAJOR_VER@.@MINOR_VER1@.@MINOR_VER2@.@MINOR_VER3@\0"
7 |
8 | #define VER_PRODUCTVERSION @MAJOR_VER@,@MINOR_VER1@,@MINOR_VER2@,@MINOR_VER3@
9 | #define VER_PRODUCTVERSION_STR "@MAJOR_VER@.@MINOR_VER1@.@MINOR_VER2@.@MINOR_VER3@\0"
10 |
11 |
12 | 1 VERSIONINFO
13 | FILEVERSION VER_FILEVERSION
14 | PRODUCTVERSION VER_PRODUCTVERSION
15 | FILEFLAGSMASK 0x3fL
16 | #ifdef _DEBUG
17 | FILEFLAGS 0x1L
18 | #else
19 | FILEFLAGS 0x0L
20 | #endif
21 | FILEOS VOS_NT_WINDOWS32
22 | FILETYPE VFT_APP
23 | FILESUBTYPE 0x0L
24 | BEGIN
25 | BLOCK "StringFileInfo"
26 | BEGIN
27 | BLOCK "040904e4"
28 | BEGIN
29 | VALUE "CompanyName", "@COMPANYNAME@\0"
30 | VALUE "FileDescription", "@PRODUCTNAME@\0"
31 | VALUE "FileVersion", VER_FILEVERSION_STR
32 | VALUE "LegalCopyright", "Copyright (C) 2013 @COMPANYNAME@ All Rights Reserved.\0"
33 | VALUE "ProductName", "@PRODUCTNAME@\0"
34 | VALUE "ProductVersion", VER_PRODUCTVERSION_STR
35 | VALUE "OriginalFilename", "@SHORTPRODUCTNAME@.exe\0"
36 | VALUE "InternalName", "@SHORTPRODUCTNAME@\0"
37 | END
38 | END
39 | BLOCK "VarFileInfo"
40 | BEGIN
41 | /* The following line should only be modified for localized versions. */
42 | /* It consists of any number of WORD,WORD pairs, with each pair */
43 | /* describing a language,codepage combination supported by the file. */
44 | /* */
45 | /* For example, a file might have values "0x409,1252" indicating that it */
46 | /* supports English language (0x409) in the Windows ANSI codepage (1252). */
47 |
48 | VALUE "Translation", 0x409, 1252
49 | END
50 | END
51 |
--------------------------------------------------------------------------------
/QtPlayer/videocontrol.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class VideoPlayerWidget;
6 |
7 | namespace Ui
8 | {
9 | class VideoControl;
10 | }
11 |
12 | class VideoControl : public QWidget
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit VideoControl(VideoPlayerWidget* parent = nullptr);
18 | ~VideoControl() override;
19 | void setVolume(int volume, bool onlyWidget = false);
20 | void showPlaybutton(bool show = true);
21 |
22 | int getHeight() const { return m_height; };
23 | int getWidth() const;
24 |
25 | signals:
26 | void download();
27 | void browse();
28 |
29 | protected:
30 | bool eventFilter(QObject* obj, QEvent* event) override;
31 | void paintEvent(QPaintEvent* event) override;
32 | void resizeEvent(QResizeEvent* event)override;
33 | void wheelEvent(QWheelEvent* event) override;
34 |
35 | public slots:
36 | void on_btnPlay_clicked();
37 | void on_btnPause_clicked();
38 |
39 | private slots:
40 | void onProgramVolumeChange(double volume);
41 | void on_btnVolume_clicked();
42 | void on_btnStop_clicked();
43 | void on_btnBrowser_clicked();
44 |
45 | private:
46 | Ui::VideoControl* ui;
47 | VideoPlayerWidget* videoPlayer;
48 | int m_height;
49 | QPixmap background;
50 | QPixmap backgroundfs;
51 | bool m_isVolumeOn{false};
52 | int m_prevVolumeValue{0};
53 |
54 | void switchVolumeButton(bool volumeOn);
55 | };
56 |
--------------------------------------------------------------------------------
/QtPlayer/videodisplay.cpp:
--------------------------------------------------------------------------------
1 | #include "videodisplay.h"
2 |
3 | VideoDisplay::VideoDisplay() = default;
4 |
5 | VideoDisplay::~VideoDisplay()
6 | {
7 | if (m_decoder != nullptr) {
8 | m_decoder->setFrameListener(nullptr);
9 | }
10 | }
11 |
12 | void VideoDisplay::setDecoderObject(FFmpegDecoderWrapper* decoder)
13 | {
14 | Q_ASSERT(decoder != nullptr);
15 | if (m_decoder != decoder)
16 | {
17 | m_decoder = decoder;
18 | m_decoder->setFrameListener(this);
19 | m_decoder->getFrameDecoder()->SetFrameFormat(
20 | #ifdef DEVELOPER_OPENGL
21 | IFrameDecoder::PIX_FMT_YUV420P
22 | #else
23 | IFrameDecoder::PIX_FMT_RGB24
24 | #endif
25 | , false);
26 | }
27 | }
28 |
29 | void VideoDisplay::finishedDisplayingFrame(unsigned int generation)
30 | {
31 | m_decoder->finishedDisplayingFrame(generation);
32 | }
33 |
--------------------------------------------------------------------------------
/QtPlayer/videodisplay.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include "ffmpegdecoder.h"
6 |
7 | class VideoDisplay : public IFrameListener
8 | {
9 | public:
10 | VideoDisplay();
11 | ~VideoDisplay() override;
12 | void finishedDisplayingFrame(unsigned int generation);
13 | void setDecoderObject(FFmpegDecoderWrapper* decoder);
14 |
15 | virtual void showPicture(const QImage& picture) = 0;
16 | virtual void showPicture(const QPixmap& picture) = 0;
17 |
18 | void setPreferredSize(int scrWidth, int scrHeight)
19 | {
20 | m_scrWidth = scrWidth;
21 | m_scrHeight = scrHeight;
22 | }
23 |
24 | protected:
25 | FFmpegDecoderWrapper* m_decoder{nullptr};
26 | int m_scrWidth{};
27 | int m_scrHeight{};
28 | };
29 |
--------------------------------------------------------------------------------
/QtPlayer/videoplayer.cpp:
--------------------------------------------------------------------------------
1 | #include "videoplayer.h"
2 | #include "widgetdisplay.h"
3 |
4 | #include
5 |
6 | VideoPlayer::VideoPlayer() = default;
7 |
8 | VideoPlayer::~VideoPlayer()
9 | {
10 | delete m_display;
11 | }
12 |
13 | FFmpegDecoderWrapper* VideoPlayer::getDecoder()
14 | {
15 | return &m_decoder;
16 | }
17 |
18 | VideoDisplay* VideoPlayer::getCurrentDisplay()
19 | {
20 | return m_display;
21 | }
22 |
23 | void VideoPlayer::setDisplay(VideoDisplay* display)
24 | {
25 | Q_ASSERT(display);
26 | delete m_display;
27 |
28 | m_display = display;
29 | m_decoder.setFrameListener(m_display);
30 | }
31 |
32 | void VideoPlayer::setState(VideoState newState)
33 | {
34 | qDebug() << __FUNCTION__ << "newState:" << newState;
35 | m_state = newState;
36 | }
37 |
--------------------------------------------------------------------------------
/QtPlayer/videoplayer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "ffmpegdecoder.h"
4 |
5 |
6 | class VideoPlayer
7 | {
8 | public:
9 | enum VideoState
10 | {
11 | InitialState,
12 | Playing,
13 | Paused,
14 | };
15 |
16 | VideoPlayer();
17 | virtual ~VideoPlayer();
18 |
19 | FFmpegDecoderWrapper* getDecoder();
20 | VideoDisplay* getCurrentDisplay();
21 | virtual void setDisplay(VideoDisplay* display);
22 | VideoState state() const { return m_state; }
23 |
24 | protected:
25 | void setState(VideoState newState);
26 |
27 | private:
28 | FFmpegDecoderWrapper m_decoder;
29 | VideoDisplay* m_display{nullptr};
30 | VideoState m_state{InitialState};
31 | };
32 |
--------------------------------------------------------------------------------
/QtPlayer/videoplayerwidget.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "mainwindow.h"
4 | #include "videoplayer.h"
5 |
6 | #include
7 | #include
8 |
9 | class VideoControl;
10 | class VideoProgressBar;
11 | class VideoWidget;
12 |
13 |
14 | class VideoPlayerWidget;
15 |
16 | inline VideoPlayerWidget* VideoPlayerWidgetInstance()
17 | {
18 | if (auto mainWindow = getMainWindow()) {
19 | return mainWindow->getPlayer();
20 | }
21 | return nullptr;
22 | }
23 |
24 |
25 | class VideoPlayerWidget : public QFrame, public VideoPlayer
26 | {
27 | Q_OBJECT
28 | public:
29 | explicit VideoPlayerWidget(QWidget* parent = nullptr);
30 | ~VideoPlayerWidget() override;
31 |
32 | void pauseVideo();
33 | void resumeVideo();
34 |
35 | void stopVideo(bool showDefaultImage = false);
36 | bool isPaused();
37 | void seekByPercent(float percent);
38 |
39 | VideoDisplay* getCurrentDisplay();
40 | VideoWidget* videoWidget() {return m_videoWidget;}
41 |
42 | void setProgressbar(VideoProgressBar* progressbar);
43 | void setControl(VideoControl* controlWidget);
44 |
45 | void setDefaultPreviewPicture();
46 |
47 | QString currentFilename() const;
48 |
49 | void updateLayout();
50 |
51 | void exitFullScreen();
52 |
53 | void playFile(const QString& fileName);
54 |
55 | protected:
56 | void resizeEvent(QResizeEvent* event) override;
57 | bool eventFilter(QObject* object, QEvent* event) override;
58 |
59 | public slots:
60 | void playPauseButtonAction();
61 |
62 | private slots:
63 | void setVideoFilename(const QString& fileName);
64 |
65 | void updateViewOnVideoStop(bool showDefaultImage = true);
66 |
67 | void onPlayingFinished();
68 |
69 | signals:
70 | void fileReleased();
71 |
72 | private:
73 | friend class VideoWidget;
74 |
75 | VideoControl* m_controls{nullptr};
76 | VideoProgressBar* m_progressBar{nullptr};
77 | QString m_currentFile;
78 | VideoWidget* m_videoWidget;
79 | };
80 |
--------------------------------------------------------------------------------
/QtPlayer/videoprogressbar.cpp:
--------------------------------------------------------------------------------
1 | #include "videoprogressbar.h"
2 | #include "ffmpegdecoder.h"
3 | #include "videoplayerwidget.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 | #include
11 |
12 | VideoProgressBar::VideoProgressBar(QWidget* parent) :
13 | QProgressBar(parent)
14 | {
15 | m_downloaded = 0;
16 | m_played = 0;
17 |
18 | setWindowTitle("Video Progress Bar");
19 | resize(500, 200);
20 | installEventFilter(this);
21 | }
22 |
23 | VideoProgressBar::~VideoProgressBar() = default;
24 |
25 | void VideoProgressBar::paintEvent(QPaintEvent* event)
26 | {
27 | Q_UNUSED(event)
28 | QPainter painter(this);
29 | QLinearGradient gradient(0, 0, 0, height());
30 |
31 | int lineheight = height() / 3;
32 | int margintop = (height() - lineheight) / 2;
33 |
34 | // Draw background line
35 | gradient.setColorAt(0, QColor(67, 67, 67));
36 | gradient.setColorAt(1, QColor(49, 49, 50));
37 | painter.setBrush(gradient);
38 | painter.setPen(Qt::NoPen);
39 | painter.drawRect(0, margintop, width(), lineheight);
40 |
41 | // Downloaded line
42 | gradient.setColorAt(0, QColor(235, 235, 235));
43 | gradient.setColorAt(1, QColor(207, 213, 217));
44 | painter.setBrush(gradient);
45 | painter.drawRect(0, margintop, (static_cast(m_downloaded) / m_scale) * width(), lineheight);
46 |
47 | // 3 step : playing line
48 | gradient.setColorAt(0, QColor(209, 63, 70));
49 | gradient.setColorAt(1, QColor(177, 10, 11));
50 | painter.setBrush(gradient);
51 | painter.drawRect(0, margintop, (static_cast(m_played) / m_scale) * width(), lineheight);
52 |
53 | QPixmap clicker = QPixmap(":/images/video_seek_cursor.png");
54 | painter.drawPixmap(
55 | QRect((m_played / (m_scale - static_cast(clicker.width())*m_scale / (width()))) * width() - 1 - static_cast(clicker.width())*m_played / m_scale * 1.8 , 1, clicker.width(), clicker.height()),
56 | clicker,
57 | clicker.rect()
58 | );
59 | }
60 |
61 | void VideoProgressBar::setDownloadedCounter(int downloaded)
62 | {
63 | downloaded = std::clamp(downloaded, 0, m_scale);
64 |
65 | if (m_downloaded == downloaded)
66 | {
67 | return;
68 | }
69 |
70 | m_downloaded = downloaded;
71 |
72 | repaint();
73 | }
74 |
75 | void VideoProgressBar::setPlayedCounter(int played)
76 | {
77 | if (played < 0)
78 | {
79 | played = 0;
80 | }
81 |
82 | if (m_played == played)
83 | {
84 | return;
85 | }
86 |
87 | m_played = played;
88 |
89 | repaint();
90 | }
91 |
92 | int VideoProgressBar::getScale() const
93 | {
94 | return m_scale;
95 | }
96 |
97 | void VideoProgressBar::resetProgress()
98 | {
99 | m_downloaded = 0;
100 | m_played = 0;
101 | repaint();
102 |
103 | setToolTip(QString());
104 | if (underMouse())
105 | {
106 | QToolTip::hideText();
107 | }
108 | }
109 |
110 | bool VideoProgressBar::eventFilter(QObject* obj, QEvent* event)
111 | {
112 | //const FFmpegDecoder* decoder = VideoPlayerWidgetInstance()->getDecoder();
113 | QEvent::Type eventType = event->type();
114 | switch (eventType)
115 | {
116 | case QEvent::MouseMove:
117 | {
118 | auto* mevent = static_cast(event);
119 | float percent = (mevent->x() * 1.0) / width();
120 |
121 | if (m_btn_down)
122 | {
123 | percent = std::clamp(percent, 0.F, 1.F);
124 |
125 | if (!m_seekDisabled)
126 | {
127 | VideoPlayerWidgetInstance()->seekByPercent(percent);
128 | }
129 | }
130 | }
131 | break;
132 | case QEvent::MouseButtonPress:
133 | {
134 | m_btn_down = true;
135 | }
136 | break;
137 | case QEvent::MouseButtonRelease:
138 | {
139 | auto* mevent = static_cast(event);
140 | float percent = (mevent->x() * 1.0) / width();
141 |
142 | percent = std::clamp(percent, 0.F, 1.F);
143 |
144 | if (!m_seekDisabled)
145 | {
146 | VideoPlayerWidgetInstance()->seekByPercent(percent);
147 | }
148 | m_btn_down = false;
149 | }
150 | break;
151 | default:;
152 | }
153 |
154 | return QWidget::eventFilter(obj, event);
155 | }
156 |
157 |
158 | void VideoProgressBar::displayPlayedProgress(qint64 frame, qint64 total)
159 | {
160 | int progress = (static_cast(frame) / total) * getScale();
161 | if (!m_seekDisabled)
162 | {
163 | setPlayedCounter(progress);
164 | }
165 | else
166 | {
167 | setPlayedCounter(0);
168 | }
169 | }
170 |
171 | void VideoProgressBar::seekingEnable(bool enable /* = true*/)
172 | {
173 | m_seekDisabled = !enable;
174 | }
175 |
--------------------------------------------------------------------------------
/QtPlayer/videoprogressbar.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class VideoProgressBar : public QProgressBar
6 | {
7 | Q_OBJECT
8 | public:
9 | explicit VideoProgressBar(QWidget* parent = nullptr);
10 |
11 | ~VideoProgressBar() override;
12 | int getScale() const;
13 | void resetProgress();
14 |
15 | protected:
16 | void paintEvent(QPaintEvent* event) override;
17 | bool eventFilter(QObject* obj, QEvent* event) override;
18 |
19 | private:
20 | int m_downloaded;
21 | int m_played;
22 | int m_scale{1000};
23 | bool m_btn_down{false};
24 | bool m_seekDisabled{false};
25 | qint64 m_downloadedTotalOriginal{0};
26 | public slots:
27 | void setDownloadedCounter(int downloaded);
28 | void setPlayedCounter(int played);
29 | void seekingEnable(bool enable = true);
30 | public slots:
31 | void displayPlayedProgress(qint64 frame, qint64 total);
32 | };
33 |
--------------------------------------------------------------------------------
/QtPlayer/videowidget.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #ifdef DEVELOPER_OPENGL
8 | #include "opengldisplay.h"
9 | #else
10 | #include "widgetdisplay.h"
11 | #endif
12 |
13 | class VideoPlayerWidget;
14 |
15 | // FIXME: OpenGL full support
16 | #ifdef DEVELOPER_OPENGL
17 | class VideoWidget : public OpenGLDisplay
18 | #else
19 | class VideoWidget : public WidgetDisplay
20 | #endif
21 | {
22 | Q_OBJECT
23 | Q_PROPERTY(QImage m_noPreviewImg READ noPreviewImage WRITE setNoPreviewImage);
24 | public:
25 | explicit VideoWidget(VideoPlayerWidget* parent = nullptr);
26 | ~VideoWidget() override;
27 |
28 | void setDefaultPreviewPicture();
29 | QSize getPictureSize() const { return m_pictureSize; }
30 | QPixmap originalFrame() const { return m_originalFrame; }
31 | QImage startImageButton() const { return m_startImgButton; }
32 |
33 | QImage noPreviewImage() const { return m_noPreviewImg; }
34 | void setNoPreviewImage(const QImage& noImage) { m_noPreviewImg = noImage; }
35 |
36 | QPixmap drawPreview(const QImage& fromImage);
37 | void hidePlayButton();
38 |
39 | void updatePlayButton();
40 |
41 | protected:
42 | void keyPressEvent(QKeyEvent* event) override;
43 |
44 | void mousePressEvent(QMouseEvent* event) override;
45 | void mouseReleaseEvent(QMouseEvent* event) override;
46 | void mouseMoveEvent(QMouseEvent* event) override;
47 | void wheelEvent(QWheelEvent* event) override;
48 | void resizeEvent(QResizeEvent* event) override;
49 |
50 | VideoPlayerWidget* VideoPlayerWidgetInstance();
51 |
52 | QImage m_startImgButton;
53 | QImage m_noPreviewImg;
54 | QPixmap m_originalFrame;
55 |
56 | private:
57 | bool m_playIndicator{false};
58 | QSize m_pictureSize;
59 | QImage m_defPlayButton, m_hoverPlayButton, m_clickedPlayButton;
60 | QImage* m_selImage;
61 | QImage m_fromImage;
62 | bool m_isMousePressed{false};
63 | const int m_playBtnRadius{29};
64 | #ifdef Q_OS_LINUX
65 | bool m_resizeIndicator = false;
66 | #endif
67 |
68 | qint64 m_lastMouseTime{0};
69 |
70 | QTimer m_cursorTimer;
71 |
72 | bool pointInButton(const QPoint& point);
73 |
74 | void showElements();
75 | void hideElements();
76 |
77 | public Q_SLOTS:
78 | void fullScreen(bool isEnable = true);
79 |
80 | protected Q_SLOTS:
81 | #ifndef DEVELOPER_OPENGL
82 | virtual void currentDisplay(unsigned int generation) override;
83 | #endif
84 |
85 | private Q_SLOTS:
86 | void getImageFinished(const QImage& image);
87 | void onCursorTimer();
88 | void fullScreenProcess();
89 | Q_SIGNALS:
90 | void leaveFullScreen();
91 | void mouseClicked();
92 | };
93 |
--------------------------------------------------------------------------------
/QtPlayer/volumeprogressbar.cpp:
--------------------------------------------------------------------------------
1 | #include "volumeprogressbar.h"
2 |
3 | #include
4 |
5 | VolumeProgressBar::VolumeProgressBar(QWidget* parent) : QProgressBar(parent),
6 | m_borderBrush(QColor(101, 105, 108)),
7 | m_backBrush(QColor(66, 66, 66)),
8 | m_fillBorderBrush(QColor(176, 180, 183)),
9 | m_fillBrush(QColor(255, 255, 255))
10 | {
11 | }
12 |
13 | VolumeProgressBar::~VolumeProgressBar() = default;
14 |
15 | void VolumeProgressBar::paintEvent(QPaintEvent* event)
16 | {
17 | Q_UNUSED(event)
18 | QPainter painter(this);
19 |
20 | painter.fillRect(0, 0, width(), height(), m_borderBrush);
21 | painter.fillRect(1, 1, width() - 2, height() - 2, m_backBrush);
22 |
23 | int filledWidth = static_cast(width() / 100.0 * value());
24 |
25 | painter.fillRect(0, 0, filledWidth, height(), m_fillBorderBrush);
26 | if (filledWidth > 1)
27 | {
28 | painter.fillRect(1, 1, filledWidth - 2, height() - 2, m_fillBrush);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/QtPlayer/volumeprogressbar.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | class VolumeProgressBar : public QProgressBar
6 | {
7 | Q_OBJECT
8 | public:
9 | VolumeProgressBar(QWidget* parent);
10 | ~VolumeProgressBar() override;
11 | protected:
12 | void paintEvent(QPaintEvent* event) override;
13 |
14 | private:
15 | QBrush m_borderBrush, m_backBrush;
16 | QBrush m_fillBorderBrush, m_fillBrush;
17 | };
18 |
--------------------------------------------------------------------------------
/QtPlayer/widgetdisplay.cpp:
--------------------------------------------------------------------------------
1 | #include "widgetdisplay.h"
2 |
3 | #include
4 |
5 | #include
6 |
7 | WidgetDisplay::WidgetDisplay(QWidget* parent) : QLabel(parent)
8 | {
9 | connect(this, &WidgetDisplay::display, this, &WidgetDisplay::currentDisplay);
10 | }
11 |
12 | void WidgetDisplay::currentDisplay(unsigned int generation)
13 | {
14 | m_display = QPixmap::fromImage(m_image);
15 | setPixmap(m_display);
16 |
17 | finishedDisplayingFrame(generation);
18 | }
19 |
20 |
21 | void WidgetDisplay::showPicture(const QImage& picture)
22 | {
23 | showPicture(QPixmap::fromImage(picture));
24 | }
25 |
26 | void WidgetDisplay::showPicture(const QPixmap& picture)
27 | {
28 | setPixmap(picture);
29 | }
30 |
31 |
32 | void WidgetDisplay::updateFrame(IFrameDecoder* decoder, unsigned int generation)
33 | {
34 | FrameRenderingData data;
35 | if (!decoder->getFrameRenderingData(&data))
36 | {
37 | return;
38 | }
39 |
40 | m_aspectRatio = float(data.height) / data.width;
41 |
42 | auto image = QImage(data.image[0], data.width, data.height, data.pitch[0], QImage::Format_RGB888);
43 | if (m_scrWidth > 0 && m_scrHeight > 0) {
44 | m_image = image.scaled(m_scrWidth, m_scrHeight);
45 | } else {
46 | m_image = std::move(image);
47 | }
48 | }
49 |
50 | void WidgetDisplay::drawFrame(IFrameDecoder* decoder, unsigned int generation)
51 | {
52 | emit display(generation);
53 | }
54 |
55 | void WidgetDisplay::decoderClosing()
56 | {
57 | }
58 |
--------------------------------------------------------------------------------
/QtPlayer/widgetdisplay.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "videodisplay.h"
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | class WidgetDisplay : public QLabel, public VideoDisplay
10 | {
11 | Q_OBJECT
12 | public:
13 | WidgetDisplay(QWidget* parent = nullptr);
14 | ~WidgetDisplay() override = default;
15 |
16 | void showPicture(const QImage& picture) override;
17 | void showPicture(const QPixmap& picture) override;
18 |
19 | // decoder->finishedDisplayingFrame() must be called
20 | void updateFrame(IFrameDecoder* decoder, unsigned int generation) override;
21 | void drawFrame(IFrameDecoder* decoder, unsigned int generation) override;
22 | void decoderClosing() override;
23 |
24 | float aspectRatio() const { return m_aspectRatio; }
25 |
26 | protected:
27 | QImage m_image;
28 | QPixmap m_display;
29 | float m_aspectRatio { 0.75F };
30 |
31 | protected slots:
32 | virtual void currentDisplay(unsigned int generation);
33 | signals:
34 | void display(unsigned int generation);
35 | };
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ℉ℲmpegPlayer
2 |
3 | A simple FFmpeg based player. The player core is generic and made with multiplatformity in mind. UI / video / audio layer is MFC/Win32 specific. It turns out that there is no need to use multimedia libraries. There is also a Qt based demo example included. It offers:
4 | - Basic Playback Controls: Play/Pause, Stop.
5 | - Next/Previous Frame: Step through the video one frame at a time during pause.
6 | - Speed Change: Increase or decrease the playback speed without altering the pitch of the audio.
7 | - Separate Video and Audio Inputs: Ability to load and play video and audio from separate sources.
8 | - Audio Track Selection: Choose between different audio tracks if available.
9 | - Fragment Selection for Export: Mark in and out points to select a part of the video for exporting.
10 | - Repeated Playing: Loop the entire video/playlist or selected fragment continuously.
11 | - Subtitles: Load and display subtitle files in various formats.
12 | - Super Resolution: Enhance the resolution of the video using upscaling techniques.
13 | - Codec Support: Compatibility with a wide range of video and audio codecs.
14 | - Streaming Support: Ability to stream video from online sources.
15 |
16 | [Semi transparent, click through full screen mode introduced.](https://bit.ly/2JLTbQn) It is invokable by holding ctrl+shift while pressing full screen button.
17 |
18 | ## Getting Started
19 |
20 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.
21 |
22 | ### Prerequisites
23 |
24 |
25 | - Visual Studio 2017 or higher.
26 | - vcpkg.
27 |
28 | ### Installing
29 |
30 | Be sure to download git submodules.
31 |
32 | To get a development env running:
33 |
34 | Install vcpkg from https://github.com/Microsoft/vcpkg.
35 | ```
36 | .\vcpkg integrate install
37 | ```
38 |
39 | Install Boost, FFmpeg, OpenCV etc. Details can be found in .github/workflows/msbuild.yml.
40 |
41 | Create ./Directory.Build.props file in the project folder. It contents depend on you environment, for example:
42 | ```
43 |
44 |
45 | 10.0.22621.0
46 | v4.6.2
47 | v143
48 |
49 |
50 | ```
51 |
52 | YouTube view support is turned on by default. It can be turned off by commenting define YOUTUBE_EXPERIMENT in YouTuber.cpp. A special mode has been implemented: Google can use SAN certificates that include multiple domains and subdomains. This allows one certificate to protect multiple services, such as youtube.com, www.youtube.com, and other subdomains. If you have one certificate with multiple SANs, and all domains are served by one certificate, you can do without SNI by using the IP address in the URL and the Host header to identify the content.
53 |
54 | The matching Python version has to be installed for the accessory DLLs to be accessible, except for embedded Python coming with installation. In any case Pytubefix now requires Node.js installed.
55 |
56 | You may need to remove pytube stuff from your profile folder for the player application to set up the latest version, for example, by invoking remove_pytube.cmd.
57 |
58 | You can also "patch" Python stuff by creating %LOCALAPPDATA%\git-subst.cfg mapping file.
59 |
60 | Just in case: "In fact in boost-python, the default behavior is that even when debug boost libraries are created, these libraries are linked to the release pythonX.dll/lib - by intention, according to the docs." https://github.com/pybind/pybind11/issues/1295
61 |
62 | Tiny demos here: https://www.youtube.com/watch?v=dySA4yEGdEc https://www.youtube.com/watch?v=t5iW2ZsEzrA
63 |
64 | Tip: hold Ctrl+Shift while submitting File Open dialog to choose a separate audio file. It works for the file opening from the Windows Explorer as well.
65 |
66 | Please take into account specific Windows 10 behavior while opening Internet shortcuts: https://community.spiceworks.com/topic/1968971-opening-web-links-downloading-1-item-to-zcrksihu You can avoid this by dragging and dropping them.
67 |
68 | Note that the FFmpeg patch speeds up HEVC decoding without GPU support by ~10%:
69 |
70 | 
71 |
72 | ### Bonus tip
73 |
74 | Playing YouTube videos in browsers may result in poor performance on slow hardware. Assign a keyboard shortcut to the FFmpeg player by editing its shortcut. Hover your mouse over the YouTube link in Firefox and bring up the shortcut. A player pop-up window will appear, starting the video playback. The same can be achieved in Chrome with some tweaking. [Start Chrome with this flag: --force-renderer-accessibility](https://www.chromium.org/developers/design-documents/accessibility/) and / or [set up IAccessible2 COM proxy stub DLL](https://github.com/aliakseis/IAccessible2Proxy).
75 |
76 | 
77 |
--------------------------------------------------------------------------------
/Setup/python-embed-win32.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aliakseis/FFmpegPlayer/ecbb1813c983a559d4276e1a5d13a8a5721caf61/Setup/python-embed-win32.7z
--------------------------------------------------------------------------------
/ToUTF8/ToUTF8.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
--------------------------------------------------------------------------------
/audio/AudioPitchDecorator.cpp:
--------------------------------------------------------------------------------
1 | #include "AudioPitchDecorator.h"
2 |
3 | #include "smbPitchShift.h"
4 |
5 | #include
6 | #include
7 |
8 | AudioPitchDecorator::AudioPitchDecorator(std::unique_ptr player
9 | , std::function getPitchShift)
10 | : m_player(std::move(player))
11 | , m_getPitchShift(std::move(getPitchShift))
12 | {
13 | }
14 |
15 | AudioPitchDecorator::~AudioPitchDecorator() = default;
16 |
17 | void AudioPitchDecorator::SetCallback(IAudioPlayerCallback * callback)
18 | {
19 | m_player->SetCallback(callback);
20 | }
21 |
22 | void AudioPitchDecorator::InitializeThread()
23 | {
24 | m_player->InitializeThread();
25 | }
26 |
27 | void AudioPitchDecorator::DeinitializeThread()
28 | {
29 | m_player->DeinitializeThread();
30 | }
31 |
32 | void AudioPitchDecorator::WaveOutReset()
33 | {
34 | m_player->WaveOutReset();
35 | for (auto& v : m_smbPitchShifts)
36 | v.reset();
37 | }
38 |
39 | void AudioPitchDecorator::Close()
40 | {
41 | m_player->Close();
42 | }
43 |
44 | bool AudioPitchDecorator::Open(int bytesPerSample, int channels, int * samplesPerSec)
45 | {
46 | if (!m_player->Open(bytesPerSample, channels, samplesPerSec))
47 | return false;
48 |
49 | m_bytesPerSample = bytesPerSample;
50 | m_samplesPerSec = *samplesPerSec;
51 | m_smbPitchShifts.resize(channels);
52 | for (auto& v : m_smbPitchShifts)
53 | v.reset();
54 |
55 | return true;
56 | }
57 |
58 | void AudioPitchDecorator::SetVolume(double volume)
59 | {
60 | m_player->SetVolume(volume);
61 | }
62 |
63 | double AudioPitchDecorator::GetVolume() const
64 | {
65 | return m_player->GetVolume();
66 | }
67 |
68 | void AudioPitchDecorator::WaveOutPause()
69 | {
70 | m_player->WaveOutPause();
71 | }
72 |
73 | void AudioPitchDecorator::WaveOutRestart()
74 | {
75 | m_player->WaveOutRestart();
76 | }
77 |
78 | bool AudioPitchDecorator::WriteAudio(uint8_t * write_data, int64_t write_size)
79 | {
80 | const auto pitchShift = m_getPitchShift();
81 | if (pitchShift != 1. && m_bytesPerSample == 2)
82 | {
83 | const auto numSamples = (write_size / m_bytesPerSample) / m_smbPitchShifts.size();
84 | if (m_buffer.size() < numSamples)
85 | m_buffer.resize(numSamples);
86 | int16_t* const intData = (int16_t*)write_data;
87 | for (int i = 0; i < m_smbPitchShifts.size(); ++i)
88 | {
89 | for (size_t j = 0; j < numSamples; ++j)
90 | {
91 | m_buffer[j] = intData[j * m_smbPitchShifts.size() + i] / 32768.;
92 | }
93 | m_smbPitchShifts[i].smbPitchShift(
94 | pitchShift, numSamples, 4096, 16, m_samplesPerSec, m_buffer.data(), m_buffer.data());
95 | for (size_t j = 0; j < numSamples; ++j)
96 | {
97 | // decrease level to avoid clipping distortions
98 | intData[j * m_smbPitchShifts.size() + i] = std::clamp(m_buffer[j], -2.f, 2.f) * (32767. / 2);
99 | }
100 | }
101 | }
102 | else
103 | {
104 | for (auto& v : m_smbPitchShifts)
105 | v.reset();
106 | }
107 | return m_player->WriteAudio(write_data, write_size);
108 | }
109 |
--------------------------------------------------------------------------------
/audio/AudioPitchDecorator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../video/audioplayer.h"
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | class CSmbPitchShift;
10 |
11 | class AudioPitchDecorator :
12 | public IAudioPlayer
13 | {
14 | public:
15 | AudioPitchDecorator(std::unique_ptr player,
16 | std::function getPitchShift);
17 | ~AudioPitchDecorator();
18 |
19 | AudioPitchDecorator(const AudioPitchDecorator&) = delete;
20 | AudioPitchDecorator& operator =(const AudioPitchDecorator&) = delete;
21 |
22 | // Inherited via IAudioPlayer
23 | void SetCallback(IAudioPlayerCallback * callback) override;
24 | void InitializeThread() override;
25 | void DeinitializeThread() override;
26 | void WaveOutReset() override;
27 | void Close() override;
28 | bool Open(int bytesPerSample, int channels, int * samplesPerSec) override;
29 | void SetVolume(double volume) override;
30 | double GetVolume() const override;
31 | void WaveOutPause() override;
32 | void WaveOutRestart() override;
33 | bool WriteAudio(uint8_t * write_data, int64_t write_size) override;
34 |
35 | private:
36 | std::unique_ptr m_player;
37 | std::function m_getPitchShift;
38 | std::vector m_smbPitchShifts;
39 |
40 | std::vector m_buffer;
41 |
42 | int m_bytesPerSample{};
43 | int m_samplesPerSec{};
44 | };
45 |
46 |
--------------------------------------------------------------------------------
/audio/AudioPlayerImpl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../video/audioplayer.h"
4 |
5 | #include
6 | #include
7 |
8 | class AudioPlayerImpl :
9 | public IAudioPlayer
10 | {
11 | public:
12 | AudioPlayerImpl();
13 | ~AudioPlayerImpl() override;
14 |
15 | AudioPlayerImpl(const AudioPlayerImpl&) = delete;
16 | AudioPlayerImpl& operator=(const AudioPlayerImpl&) = delete;
17 |
18 | void SetCallback(IAudioPlayerCallback* callback) override
19 | {
20 | m_callback = callback;
21 | }
22 |
23 | void InitializeThread() override;
24 | void DeinitializeThread() override;
25 |
26 | void WaveOutReset() override;
27 |
28 | void Close() override;
29 | bool Open(int bytesPerSample, int channels, int* samplesPerSec) override;
30 |
31 | void SetVolume(double volume) override;
32 | double GetVolume() const override;
33 |
34 | void WaveOutPause() override;
35 | void WaveOutRestart() override;
36 |
37 | bool WriteAudio(uint8_t* write_data, int64_t write_size) override;
38 |
39 | private:
40 | IAudioPlayerCallback* m_callback;
41 |
42 | HWAVEOUT m_waveOutput;
43 |
44 | static void CALLBACK waveOutProc(HWAVEOUT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR);
45 |
46 | WAVEHDR* m_waveBlocks;
47 | volatile long m_waveFreeBlockCount {};
48 | HANDLE m_evtHasFreeBlocks;
49 | int m_waveCurrentBlock {};
50 |
51 | int m_bytesPerSecond;
52 | };
53 |
54 |
--------------------------------------------------------------------------------
/audio/AudioPlayerWasapi.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../video/audioplayer.h"
4 |
5 | #include
6 |
7 | struct IAudioClient;
8 | struct IAudioRenderClient;
9 | struct ISimpleAudioVolume;
10 |
11 | class AudioPlayerWasapi :
12 | public IAudioPlayer
13 | {
14 | public:
15 | AudioPlayerWasapi();
16 | ~AudioPlayerWasapi() override;
17 |
18 | AudioPlayerWasapi(const AudioPlayerWasapi&) = delete;
19 | AudioPlayerWasapi& operator=(const AudioPlayerWasapi&) = delete;
20 |
21 | void SetCallback(IAudioPlayerCallback* callback) override
22 | {
23 | m_callback = callback;
24 | }
25 |
26 | void InitializeThread() override;
27 | void DeinitializeThread() override;
28 |
29 | void WaveOutReset() override;
30 |
31 | void Close() override;
32 | bool Open(int bytesPerSample, int channels, int* samplesPerSec) override;
33 |
34 | void SetVolume(double volume) override;
35 | double GetVolume() const override;
36 |
37 | void WaveOutPause() override;
38 | void WaveOutRestart() override;
39 |
40 | bool WriteAudio(uint8_t* write_data, int64_t write_size) override;
41 |
42 | private:
43 | IAudioPlayerCallback* m_callback;
44 |
45 | HANDLE m_hAudioSamplesRenderEvent;
46 |
47 | CComPtr m_AudioClient;
48 | CComPtr m_RenderClient;
49 | CComPtr m_SimpleAudioVolume;
50 |
51 | unsigned int m_BufferSize;
52 | unsigned int m_FrameSize;
53 | unsigned int m_samplesPerSec;
54 |
55 | HANDLE m_mmcssHandle;
56 |
57 | bool m_coUnitialize;
58 | };
59 |
--------------------------------------------------------------------------------
/audio/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | STATIC LIBRARY : audio Project Overview
3 | ========================================================================
4 |
5 | AppWizard has created this audio library project for you.
6 |
7 | No source files were created as part of your project.
8 |
9 |
10 | audio.vcxproj
11 | This is the main project file for VC++ projects generated using an Application Wizard.
12 | It contains information about the version of Visual C++ that generated the file, and
13 | information about the platforms, configurations, and project features selected with the
14 | Application Wizard.
15 |
16 | audio.vcxproj.filters
17 | This is the filters file for VC++ projects generated using an Application Wizard.
18 | It contains information about the association between the files in your project
19 | and the filters. This association is used in the IDE to show grouping of files with
20 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the
21 | "Source Files" filter).
22 |
23 | /////////////////////////////////////////////////////////////////////////////
24 | Other notes:
25 |
26 | AppWizard uses "TODO:" comments to indicate parts of the source code you
27 | should add to or customize.
28 |
29 | /////////////////////////////////////////////////////////////////////////////
30 |
--------------------------------------------------------------------------------
/audio/audio.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 |
35 |
36 | Source Files
37 |
38 |
39 | Source Files
40 |
41 |
42 | Source Files
43 |
44 |
45 | Source Files
46 |
47 |
48 |
--------------------------------------------------------------------------------
/audio/smbPitchShift.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/
4 |
5 | class CSmbPitchShift
6 | {
7 | enum { MAX_FRAME_LENGTH = 8192 };
8 |
9 | public:
10 | void reset()
11 | {
12 | gRover = 0;
13 | gInit = false;
14 | }
15 | void smbPitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata);
16 |
17 | private:
18 | float gInFIFO[MAX_FRAME_LENGTH];
19 | float gOutFIFO[MAX_FRAME_LENGTH];
20 | float gFFTworksp[2 * MAX_FRAME_LENGTH];
21 | float gLastPhase[MAX_FRAME_LENGTH / 2 + 1];
22 | float gSumPhase[MAX_FRAME_LENGTH / 2 + 1];
23 | float gOutputAccum[2 * MAX_FRAME_LENGTH];
24 | float gAnaFreq[MAX_FRAME_LENGTH];
25 | float gAnaMagn[MAX_FRAME_LENGTH];
26 | float gSynFreq[MAX_FRAME_LENGTH];
27 | float gSynMagn[MAX_FRAME_LENGTH];
28 |
29 | float gErrors[MAX_FRAME_LENGTH];
30 |
31 | long gRover = 0;
32 | bool gInit = false;
33 | };
--------------------------------------------------------------------------------
/core/ac_export.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef AC_EXPORT_H
3 | #define AC_EXPORT_H
4 |
5 | #ifdef AC_STATIC_DEFINE
6 | # define AC_EXPORT
7 | # define AC_NO_EXPORT
8 | #else
9 | # ifndef AC_EXPORT
10 | # ifdef Anime4KCPPCore_EXPORTS
11 | /* We are building this library */
12 | # define AC_EXPORT
13 | # else
14 | /* We are using this library */
15 | # define AC_EXPORT
16 | # endif
17 | # endif
18 |
19 | # ifndef AC_NO_EXPORT
20 | # define AC_NO_EXPORT
21 | # endif
22 | #endif
23 |
24 | #ifndef AC_DEPRECATED
25 | # define AC_DEPRECATED __declspec(deprecated)
26 | #endif
27 |
28 | #ifndef AC_DEPRECATED_EXPORT
29 | # define AC_DEPRECATED_EXPORT AC_EXPORT AC_DEPRECATED
30 | #endif
31 |
32 | #ifndef AC_DEPRECATED_NO_EXPORT
33 | # define AC_DEPRECATED_NO_EXPORT AC_NO_EXPORT AC_DEPRECATED
34 | #endif
35 |
36 | #if 0 /* DEFINE_NO_DEPRECATED */
37 | # ifndef AC_NO_DEPRECATED
38 | # define AC_NO_DEPRECATED
39 | # endif
40 | #endif
41 |
42 | #endif /* AC_EXPORT_H */
43 |
--------------------------------------------------------------------------------
/edit_git_subst_cfg.cmd:
--------------------------------------------------------------------------------
1 | notepad.exe "%LOCALAPPDATA%\git-subst.cfg"
2 |
--------------------------------------------------------------------------------
/networking/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | STATIC LIBRARY : unzip Project Overview
3 | ========================================================================
4 |
5 | AppWizard has created this unzip library project for you.
6 |
7 | No source files were created as part of your project.
8 |
9 |
10 | unzip.vcxproj
11 | This is the main project file for VC++ projects generated using an Application Wizard.
12 | It contains information about the version of Visual C++ that generated the file, and
13 | information about the platforms, configurations, and project features selected with the
14 | Application Wizard.
15 |
16 | unzip.vcxproj.filters
17 | This is the filters file for VC++ projects generated using an Application Wizard.
18 | It contains information about the association between the files in your project
19 | and the filters. This association is used in the IDE to show grouping of files with
20 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the
21 | "Source Files" filter).
22 |
23 | /////////////////////////////////////////////////////////////////////////////
24 | Other notes:
25 |
26 | AppWizard uses "TODO:" comments to indicate parts of the source code you
27 | should add to or customize.
28 |
29 | /////////////////////////////////////////////////////////////////////////////
30 |
--------------------------------------------------------------------------------
/networking/crypt.h:
--------------------------------------------------------------------------------
1 | /* crypt.h -- base code for crypt/uncrypt ZIPfile
2 |
3 |
4 | Version 1.01e, February 12th, 2005
5 |
6 | Copyright (C) 1998-2005 Gilles Vollant
7 |
8 | This code is a modified version of crypting code in Infozip distribution
9 |
10 | The encryption/decryption parts of this source code (as opposed to the
11 | non-echoing password parts) were originally written in Europe. The
12 | whole source package can be freely distributed, including from the USA.
13 | (Prior to January 2000, re-export from the US was a violation of US law.)
14 |
15 | This encryption code is a direct transcription of the algorithm from
16 | Roger Schlafly, described by Phil Katz in the file appnote.txt. This
17 | file (appnote.txt) is distributed with the PKZIP program (even in the
18 | version without encryption capabilities).
19 |
20 | If you don't need crypting in your application, just define symbols
21 | NOCRYPT and NOUNCRYPT.
22 |
23 | This code support the "Traditional PKWARE Encryption".
24 |
25 | The new AES encryption added on Zip format by Winzip (see the page
26 | http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
27 | Encryption is not supported.
28 | */
29 |
30 |
31 | #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
32 |
33 | /***********************************************************************
34 | * Return the next byte in the pseudo-random sequence
35 | */
36 | static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab )
37 | {
38 | //(void) pcrc_32_tab; /* avoid "unused parameter" warning */
39 | unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
40 | * unpredictable manner on 16-bit systems; not a problem
41 | * with any known compiler so far, though */
42 |
43 | temp = ((unsigned)(*(pkeys + 2)) & 0xffff) | 2;
44 | return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
45 | }
46 |
47 | /***********************************************************************
48 | * Update the encryption keys with the next byte of plain text
49 | */
50 | static int update_keys(unsigned long* pkeys, const unsigned long* pcrc_32_tab, int c)
51 | {
52 | (*(pkeys + 0)) = CRC32((*(pkeys + 0)), c);
53 | (*(pkeys + 1)) += (*(pkeys + 0)) & 0xff;
54 | (*(pkeys + 1)) = (*(pkeys + 1)) * 134775813L + 1;
55 | {
56 | register int keyshift = (int)((*(pkeys + 1)) >> 24);
57 | (*(pkeys + 2)) = CRC32((*(pkeys + 2)), keyshift);
58 | }
59 | return c;
60 | }
61 |
62 |
63 | /***********************************************************************
64 | * Initialize the encryption keys and the random header according to
65 | * the given password.
66 | */
67 | static void init_keys(const char* passwd, unsigned long* pkeys, const unsigned long* pcrc_32_tab)
68 | {
69 | *(pkeys + 0) = 305419896L;
70 | *(pkeys + 1) = 591751049L;
71 | *(pkeys + 2) = 878082192L;
72 | while (*passwd != '\0')
73 | {
74 | update_keys(pkeys, pcrc_32_tab, (int)*passwd);
75 | passwd++;
76 | }
77 | }
78 |
79 | #define zdecode(pkeys,pcrc_32_tab,c) \
80 | (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
81 |
82 | #define zencode(pkeys,pcrc_32_tab,c,t) \
83 | (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
84 |
85 | #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
86 |
87 | #define RAND_HEAD_LEN 12
88 | /* "last resort" source for second part of crypt seed pattern */
89 | # ifndef ZCR_SEED2
90 | # define ZCR_SEED2 3141592654UL /* use PI as default pattern */
91 | # endif
92 |
93 | static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
94 | const char* passwd; /* password string */
95 | unsigned char* buf; /* where to write header */
96 | int bufSize;
97 | unsigned long* pkeys;
98 | const unsigned long* pcrc_32_tab;
99 | unsigned long crcForCrypting;
100 | {
101 | int n; /* index in random header */
102 | int t; /* temporary */
103 | int c; /* random byte */
104 | unsigned char header[RAND_HEAD_LEN - 2]; /* random header */
105 | static unsigned calls = 0; /* ensure different random header each time */
106 |
107 | if (bufSize < RAND_HEAD_LEN)
108 | return 0;
109 |
110 | /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
111 | * output of rand() to get less predictability, since rand() is
112 | * often poorly implemented.
113 | */
114 | if (++calls == 1)
115 | {
116 | srand((unsigned)(time(NULL) ^ ZCR_SEED2));
117 | }
118 | init_keys(passwd, pkeys, pcrc_32_tab);
119 | for (n = 0; n < RAND_HEAD_LEN - 2; n++)
120 | {
121 | c = (rand() >> 7) & 0xff;
122 | header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
123 | }
124 | /* Encrypt random header (last two bytes is high word of crc) */
125 | init_keys(passwd, pkeys, pcrc_32_tab);
126 | for (n = 0; n < RAND_HEAD_LEN - 2; n++)
127 | {
128 | buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
129 | }
130 | buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
131 | buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
132 | return n;
133 | }
134 |
135 | #endif
136 |
--------------------------------------------------------------------------------
/networking/http_download.cpp:
--------------------------------------------------------------------------------
1 | #include "http_download.h"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | //#pragma comment(lib, "Winhttp")
15 |
16 | namespace {
17 |
18 | auto MakeGuard(HINTERNET h)
19 | {
20 | if (!h)
21 | {
22 | const DWORD errorCode = GetLastError();
23 | throw std::system_error(
24 | errorCode, std::system_category(), "HINTERNET object creation failed.");
25 | }
26 |
27 | return std::unique_ptr, decltype(&WinHttpCloseHandle)>
28 | (h, WinHttpCloseHandle);
29 | }
30 |
31 | } // namespace
32 |
33 | bool HttpDownload(const TCHAR* url, const TCHAR* path)
34 | {
35 | std::wstring wszUrl(url, url + _tcslen(url));
36 | URL_COMPONENTS urlComp{ sizeof(urlComp) };
37 |
38 | // Set required component lengths to non-zero
39 | // so that they are cracked.
40 | urlComp.dwSchemeLength = (DWORD)-1;
41 | urlComp.dwHostNameLength = (DWORD)-1;
42 | urlComp.dwUrlPathLength = (DWORD)-1;
43 | urlComp.dwExtraInfoLength = (DWORD)-1;
44 |
45 | if (!WinHttpCrackUrl(wszUrl.c_str(), wszUrl.length(), 0, &urlComp))
46 | {
47 | fprintf(stderr, "Error %u in WinHttpCrackUrl.\n", GetLastError());
48 | return false;
49 | }
50 |
51 | // Use WinHttpOpen to obtain a session handle.
52 | auto hSession = MakeGuard(WinHttpOpen(L"HttpDownload/1.0",
53 | WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
54 | WINHTTP_NO_PROXY_NAME,
55 | WINHTTP_NO_PROXY_BYPASS, 0));
56 |
57 | // Specify an HTTP server.
58 | std::wstring szHostName(
59 | urlComp.lpszHostName, urlComp.lpszHostName + urlComp.dwHostNameLength);
60 |
61 | auto hConnect = MakeGuard(WinHttpConnect(hSession.get(), szHostName.c_str(),
62 | urlComp.nPort, 0));
63 |
64 | // Create an HTTP request handle.
65 | auto hRequest = MakeGuard(WinHttpOpenRequest(hConnect.get(), L"GET",
66 | urlComp.lpszUrlPath,
67 | NULL, WINHTTP_NO_REFERER,
68 | WINHTTP_DEFAULT_ACCEPT_TYPES,
69 | (urlComp.nScheme == INTERNET_SCHEME_HTTPS)? WINHTTP_FLAG_SECURE : 0));
70 |
71 | // Send a request.
72 | BOOL bResults = WinHttpSendRequest(hRequest.get(),
73 | WINHTTP_NO_ADDITIONAL_HEADERS, 0,
74 | WINHTTP_NO_REQUEST_DATA, 0,
75 | 0, 0);
76 |
77 | // End the request.
78 | if (bResults)
79 | bResults = WinHttpReceiveResponse(hRequest.get(), NULL);
80 |
81 | // Keep checking for data until there is nothing left.
82 | if (bResults)
83 | {
84 | std::ofstream f(path, std::ofstream::binary);
85 | std::vector buf;
86 | for (;;)
87 | {
88 | DWORD dwSize = 0;
89 | // Check for available data.
90 | if (!WinHttpQueryDataAvailable(hRequest.get(), &dwSize))
91 | fprintf(stderr, "Error %u in WinHttpQueryDataAvailable.\n",
92 | GetLastError());
93 |
94 | if (dwSize == 0)
95 | break;
96 |
97 | // Allocate space for the buffer.
98 | if (buf.size() < dwSize)
99 | buf.resize(dwSize);
100 |
101 | DWORD dwDownloaded = 0;
102 |
103 | if (WinHttpReadData(hRequest.get(), buf.data(),
104 | dwSize, &dwDownloaded))
105 | {
106 | f.write(buf.data(), dwDownloaded);
107 | }
108 | else
109 | {
110 | fprintf(stderr, "Error %u in WinHttpReadData.\n", GetLastError());
111 | }
112 | }
113 | }
114 |
115 |
116 | // Report any errors.
117 | if (!bResults)
118 | fprintf(stderr, "Error %d has occurred.\n", GetLastError());
119 |
120 | return !!bResults;
121 | }
122 |
--------------------------------------------------------------------------------
/networking/http_download.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | bool HttpDownload(const TCHAR* url, const TCHAR* path);
6 |
7 |
--------------------------------------------------------------------------------
/networking/http_get.cpp:
--------------------------------------------------------------------------------
1 | #include "http_get.h"
2 |
3 | #include "httprequest_h.h"
4 |
5 | #include
6 |
7 | #include
8 |
9 | namespace {
10 |
11 | const wchar_t USER_AGENT[]
12 | = L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.75 Safari/537.36";
13 |
14 | class CComUsageScope
15 | {
16 | bool m_bInitialized;
17 | public:
18 | explicit CComUsageScope(DWORD dwCoInit = COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY)
19 | {
20 | m_bInitialized = SUCCEEDED(CoInitializeEx(NULL, dwCoInit));
21 | }
22 | ~CComUsageScope()
23 | {
24 | if (m_bInitialized)
25 | CoUninitialize();
26 | }
27 | };
28 |
29 | std::string resolveHostnameToIP(const std::string& hostname) {
30 | addrinfo hints = { 0 }, * res = nullptr;
31 | hints.ai_family = AF_INET; // Allow IPv4
32 | hints.ai_socktype = SOCK_STREAM;
33 | hints.ai_protocol = IPPROTO_TCP;
34 |
35 | if (getaddrinfo(hostname.c_str(), nullptr, &hints, &res) != 0) {
36 | return {};
37 | }
38 |
39 | char ipStr[INET6_ADDRSTRLEN];
40 | void* addr;
41 |
42 | if (res->ai_family == AF_INET) { // IPv4
43 | sockaddr_in* sockaddr_ipv4 = reinterpret_cast(res->ai_addr);
44 | addr = &(sockaddr_ipv4->sin_addr);
45 | }
46 | else if (res->ai_family == AF_INET6) { // IPv6
47 | sockaddr_in6* sockaddr_ipv6 = reinterpret_cast(res->ai_addr);
48 | addr = &(sockaddr_ipv6->sin6_addr);
49 | }
50 | else {
51 | freeaddrinfo(res);
52 | return {};
53 | }
54 |
55 | inet_ntop(res->ai_family, addr, ipStr, sizeof(ipStr));
56 | freeaddrinfo(res);
57 |
58 | return std::string(ipStr);
59 | }
60 |
61 | } // namespace
62 |
63 |
64 | long HttpGetStatus(std::string& url, bool useSAN)
65 | {
66 | if (useSAN)
67 | {
68 | auto matchEnd = std::mismatch(url.begin(), url.end(), "https://",
69 | [](char c1, char c2) { return tolower(c1) == tolower(c2); });
70 | if (matchEnd.first == url.end() || *matchEnd.second != '\0')
71 | {
72 | useSAN = false;
73 | }
74 | }
75 |
76 | CComBSTR bstrUrl;
77 | CComBSTR bstrHostname;
78 |
79 | if (useSAN)
80 | {
81 | const auto pos = 8; // Move past "://"
82 | size_t endPos = url.find_first_of(":/", pos);
83 | if (endPos != std::string::npos)
84 | {
85 | std::string hostname = url.substr(pos, endPos - pos);
86 | std::string ip = resolveHostnameToIP(hostname);
87 | if (!ip.empty()) {
88 | bstrUrl = (url.substr(0, pos) + ip + url.substr(endPos)).c_str();
89 | bstrHostname = hostname.c_str();
90 | }
91 | else
92 | {
93 | useSAN = false;
94 | }
95 | }
96 | else
97 | {
98 | useSAN = false;
99 | }
100 | }
101 |
102 | if (!useSAN)
103 | {
104 | bstrUrl = url.c_str();
105 | }
106 |
107 |
108 | VARIANT varFalse{ VT_BOOL };
109 | VARIANT varEmpty{ VT_ERROR };
110 | VARIANT varOption{ VT_I4 };
111 | varOption.intVal = 0x1000;
112 |
113 | HRESULT result = 0;
114 |
115 | CComPtr pIWinHttpRequest;
116 |
117 | CComUsageScope scope;
118 |
119 | if (FAILED(result = pIWinHttpRequest.CoCreateInstance(L"WinHttp.WinHttpRequest.5.1", NULL, CLSCTX_INPROC_SERVER)))
120 | return result;
121 |
122 | if (FAILED(result = pIWinHttpRequest->Open(CComBSTR(L"HEAD"), bstrUrl, varFalse)))
123 | return result;
124 |
125 | if (useSAN && FAILED(result = pIWinHttpRequest->SetRequestHeader(CComBSTR(L"Host"), bstrHostname)))
126 | return result;
127 |
128 | if (FAILED(result = pIWinHttpRequest->SetRequestHeader(CComBSTR(L"User-Agent"), CComBSTR(USER_AGENT))))
129 | return result;
130 |
131 | if (useSAN && FAILED(result = pIWinHttpRequest->put_Option(WinHttpRequestOption_SslErrorIgnoreFlags, varOption))) // Ignore SSL errors
132 | return result;
133 |
134 | if (FAILED(result = pIWinHttpRequest->put_Option(WinHttpRequestOption_EnableRedirects, varFalse)))
135 | return result;
136 |
137 | if (SUCCEEDED(result = pIWinHttpRequest->Send(varEmpty)))
138 | {
139 | pIWinHttpRequest->get_Status(&result);
140 | if (result == 302)
141 | {
142 | CComBSTR locationHeader;
143 | if (SUCCEEDED(pIWinHttpRequest->GetResponseHeader(CComBSTR(L"Location"), &locationHeader)))
144 | {
145 | url = CW2A(locationHeader);
146 | }
147 | }
148 | }
149 |
150 | return result;
151 | }
152 |
153 | CComVariant HttpGet(const char * url)
154 | {
155 | VARIANT varFalse{ VT_BOOL };
156 | VARIANT varEmpty{ VT_ERROR };
157 |
158 | CComVariant varBody;
159 |
160 | CComPtr pIWinHttpRequest;
161 |
162 | CComUsageScope scope;
163 |
164 | if (SUCCEEDED(pIWinHttpRequest.CoCreateInstance(L"WinHttp.WinHttpRequest.5.1", NULL, CLSCTX_INPROC_SERVER))
165 | && SUCCEEDED(pIWinHttpRequest->Open(CComBSTR(L"GET"), CComBSTR(static_cast(url)), varFalse))
166 | && SUCCEEDED(pIWinHttpRequest->SetRequestHeader(CComBSTR(L"User-Agent"), CComBSTR(USER_AGENT)))
167 | && SUCCEEDED(pIWinHttpRequest->Send(varEmpty)))
168 | {
169 | pIWinHttpRequest->get_ResponseBody(&varBody);
170 | }
171 |
172 | return varBody;
173 | }
174 |
--------------------------------------------------------------------------------
/networking/http_get.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | // modifies url if it is a redirect
7 | long HttpGetStatus(std::string& url, bool useSAN = true);
8 |
9 | CComVariant HttpGet(const char* url);
10 |
--------------------------------------------------------------------------------
/networking/httpioapi.cpp:
--------------------------------------------------------------------------------
1 | /* ioapi.c -- IO base function header for compress/uncompress .zip
2 | files using zlib + zip or unzip API
3 |
4 | Version 1.01e, February 12th, 2005
5 |
6 | Copyright (C) 1998-2005 Gilles Vollant
7 |
8 | Modified to integrate with WinHttpRequest.
9 | */
10 |
11 | #include
12 |
13 | #include "zlib.h"
14 | #include "ioapi.h"
15 |
16 | #include "httprequest_h.h"
17 |
18 | #include
19 |
20 |
21 | voidpf ZCALLBACK qiodevice_open_file_func(
22 | voidpf opaque,
23 | voidpf filename,
24 | int mode)
25 | {
26 | VARIANT varFalse{ VT_BOOL };
27 | VARIANT varEmpty{ VT_ERROR };
28 |
29 | CComVariant varStream;
30 |
31 | CComPtr pIWinHttpRequest;
32 |
33 | if (SUCCEEDED(pIWinHttpRequest.CoCreateInstance(L"WinHttp.WinHttpRequest.5.1", nullptr, CLSCTX_INPROC_SERVER))
34 | && SUCCEEDED(pIWinHttpRequest->Open(CComBSTR(L"GET"), CComBSTR(static_cast(filename)), varFalse))
35 | && SUCCEEDED(pIWinHttpRequest->Send(varEmpty))
36 | && SUCCEEDED(pIWinHttpRequest->get_ResponseStream(&varStream)))
37 | {
38 | if (CComQIPtr stream = V_UNKNOWN(&varStream))
39 | {
40 | return stream.Detach();
41 | }
42 | }
43 |
44 | return nullptr;
45 | }
46 |
47 |
48 | uLong ZCALLBACK qiodevice_read_file_func(
49 | voidpf, // opaque
50 | voidpf pf,
51 | void* buf,
52 | uLong size)
53 | {
54 | auto stream = static_cast(pf);
55 | uLong ret = 0;
56 | HRESULT hr = stream->Read(buf, size, &ret);
57 | return ret;
58 | }
59 |
60 |
61 | uLong ZCALLBACK qiodevice_write_file_func(
62 | voidpf, // opaque
63 | voidpf pf,
64 | const void* buf,
65 | uLong size)
66 | {
67 | auto stream = static_cast(pf);
68 | uLong ret = 0;
69 | stream->Write(buf, size, &ret);
70 | return ret;
71 | }
72 |
73 | uLong ZCALLBACK qiodevice_tell_file_func(
74 | voidpf, // opaque
75 | voidpf pf)
76 | {
77 | auto stream = static_cast(pf);
78 | const LARGE_INTEGER move{};
79 | ULARGE_INTEGER libNewPosition{};
80 | stream->Seek(move, STREAM_SEEK_CUR, &libNewPosition);
81 | return libNewPosition.LowPart;
82 | }
83 |
84 | int ZCALLBACK qiodevice_seek_file_func(
85 | voidpf, // opaque
86 | voidpf pf,
87 | uLong offset,
88 | int origin)
89 | {
90 | STREAM_SEEK dwOrigin;
91 | LARGE_INTEGER move;
92 | switch (origin)
93 | {
94 | case ZLIB_FILEFUNC_SEEK_CUR:
95 | dwOrigin = STREAM_SEEK_CUR;
96 | move.QuadPart = (long)offset;
97 | break;
98 | case ZLIB_FILEFUNC_SEEK_END:
99 | dwOrigin = STREAM_SEEK_END;
100 | move.QuadPart = (long)offset;
101 | break;
102 | case ZLIB_FILEFUNC_SEEK_SET:
103 | dwOrigin = STREAM_SEEK_SET;
104 | move.QuadPart = offset;
105 | break;
106 | default: return -1;
107 | }
108 | auto stream = static_cast(pf);
109 | ULARGE_INTEGER libNewPosition{};
110 | int ret = FAILED(stream->Seek(move, dwOrigin, &libNewPosition));
111 | return ret;
112 | }
113 |
114 | int ZCALLBACK qiodevice_close_file_func(
115 | voidpf, // opaque
116 | voidpf pf)
117 | {
118 | auto stream = static_cast(pf);
119 | auto cnt = stream->Release();
120 | assert(cnt == 0);
121 | return 0;
122 | }
123 |
124 | int ZCALLBACK qiodevice_error_file_func(
125 | voidpf, // opaque
126 | voidpf //stream
127 | )
128 | {
129 | return 0;
130 | }
131 |
132 | void fill_qiodevice_filefunc(
133 | zlib_filefunc_def* pzlib_filefunc_def)
134 | {
135 | pzlib_filefunc_def->zopen_file = qiodevice_open_file_func;
136 | pzlib_filefunc_def->zread_file = qiodevice_read_file_func;
137 | pzlib_filefunc_def->zwrite_file = qiodevice_write_file_func;
138 | pzlib_filefunc_def->ztell_file = qiodevice_tell_file_func;
139 | pzlib_filefunc_def->zseek_file = qiodevice_seek_file_func;
140 | pzlib_filefunc_def->zclose_file = qiodevice_close_file_func;
141 | pzlib_filefunc_def->zerror_file = qiodevice_error_file_func;
142 | pzlib_filefunc_def->opaque = nullptr;
143 | }
144 |
--------------------------------------------------------------------------------
/networking/httprequest_i.c:
--------------------------------------------------------------------------------
1 |
2 |
3 | /* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
4 |
5 | /* link this file in with the server and any clients */
6 |
7 |
8 | /* File created by MIDL compiler version 8.00.0603 */
9 | /* at Wed Jun 06 11:59:31 2018
10 | */
11 | /* Compiler settings for C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\httprequest.idl:
12 | Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0603
13 | protocol : dce , ms_ext, c_ext, robust
14 | error checks: allocation ref bounds_check enum stub_data
15 | VC __declspec() decoration level:
16 | __declspec(uuid()), __declspec(selectany), __declspec(novtable)
17 | DECLSPEC_UUID(), MIDL_INTERFACE()
18 | */
19 | /* @@MIDL_FILE_HEADING( ) */
20 |
21 | #pragma warning( disable: 4049 ) /* more than 64k source lines */
22 |
23 |
24 | #ifdef __cplusplus
25 | extern "C"{
26 | #endif
27 |
28 |
29 | #include
30 | #include
31 |
32 | #ifdef _MIDL_USE_GUIDDEF_
33 |
34 | #ifndef INITGUID
35 | #define INITGUID
36 | #include
37 | #undef INITGUID
38 | #else
39 | #include
40 | #endif
41 |
42 | #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
43 | DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
44 |
45 | #else // !_MIDL_USE_GUIDDEF_
46 |
47 | #ifndef __IID_DEFINED__
48 | #define __IID_DEFINED__
49 |
50 | typedef struct _IID
51 | {
52 | unsigned long x;
53 | unsigned short s1;
54 | unsigned short s2;
55 | unsigned char c[8];
56 | } IID;
57 |
58 | #endif // __IID_DEFINED__
59 |
60 | #ifndef CLSID_DEFINED
61 | #define CLSID_DEFINED
62 | typedef IID CLSID;
63 | #endif // CLSID_DEFINED
64 |
65 | #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
66 | const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
67 |
68 | #endif !_MIDL_USE_GUIDDEF_
69 |
70 | MIDL_DEFINE_GUID(IID, LIBID_WinHttp,0x662901fc,0x6951,0x4854,0x9e,0xb2,0xd9,0xa2,0x57,0x0f,0x2b,0x2e);
71 |
72 |
73 | MIDL_DEFINE_GUID(IID, IID_IWinHttpRequest,0x016fe2ec,0xb2c8,0x45f8,0xb2,0x3b,0x39,0xe5,0x3a,0x75,0x39,0x6b);
74 |
75 |
76 | MIDL_DEFINE_GUID(IID, IID_IWinHttpRequestEvents,0xf97f4e15,0xb787,0x4212,0x80,0xd1,0xd3,0x80,0xcb,0xbf,0x98,0x2e);
77 |
78 |
79 | MIDL_DEFINE_GUID(CLSID, CLSID_WinHttpRequest,0x2087c2f4,0x2cef,0x4953,0xa8,0xab,0x66,0x77,0x9b,0x67,0x04,0x95);
80 |
81 | #undef MIDL_DEFINE_GUID
82 |
83 | #ifdef __cplusplus
84 | }
85 | #endif
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/networking/ioapi.h:
--------------------------------------------------------------------------------
1 | /* ioapi.h -- IO base function header for compress/uncompress .zip
2 | files using zlib + zip or unzip API
3 |
4 | Version 1.01e, February 12th, 2005
5 |
6 | Copyright (C) 1998-2005 Gilles Vollant
7 |
8 | Modified to integrate with WinHttpRequest.
9 | */
10 |
11 | #ifndef _ZLIBIOAPI_H
12 | #define _ZLIBIOAPI_H
13 |
14 |
15 | #define ZLIB_FILEFUNC_SEEK_CUR (1)
16 | #define ZLIB_FILEFUNC_SEEK_END (2)
17 | #define ZLIB_FILEFUNC_SEEK_SET (0)
18 |
19 | #define ZLIB_FILEFUNC_MODE_READ (1)
20 | #define ZLIB_FILEFUNC_MODE_WRITE (2)
21 | #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
22 |
23 | #define ZLIB_FILEFUNC_MODE_EXISTING (4)
24 | #define ZLIB_FILEFUNC_MODE_CREATE (8)
25 |
26 |
27 | #ifndef ZCALLBACK
28 |
29 | #if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
30 | #define ZCALLBACK CALLBACK
31 | #else
32 | #define ZCALLBACK
33 | #endif
34 | #endif
35 |
36 | #ifdef __cplusplus
37 | extern "C" {
38 | #endif
39 |
40 | typedef voidpf(ZCALLBACK* open_file_func) OF((voidpf opaque, voidpf file, int mode));
41 | typedef uLong(ZCALLBACK* read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
42 | typedef uLong(ZCALLBACK* write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
43 | typedef uLong(ZCALLBACK* tell_file_func) OF((voidpf opaque, voidpf stream));
44 | typedef int (ZCALLBACK* seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
45 | typedef int (ZCALLBACK* close_file_func) OF((voidpf opaque, voidpf stream));
46 | typedef int (ZCALLBACK* testerror_file_func) OF((voidpf opaque, voidpf stream));
47 |
48 | typedef struct zlib_filefunc_def_s
49 | {
50 | open_file_func zopen_file;
51 | read_file_func zread_file;
52 | write_file_func zwrite_file;
53 | tell_file_func ztell_file;
54 | seek_file_func zseek_file;
55 | close_file_func zclose_file;
56 | testerror_file_func zerror_file;
57 | voidpf opaque;
58 | } zlib_filefunc_def;
59 |
60 |
61 |
62 | void fill_qiodevice_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
63 |
64 | #define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
65 | #define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
66 | #define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
67 | #define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
68 | #define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
69 | #define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
70 |
71 |
72 | #ifdef __cplusplus
73 | }
74 | #endif
75 |
76 | #endif
77 |
78 |
--------------------------------------------------------------------------------
/networking/networking.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files
35 |
36 |
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files
43 |
44 |
45 | Header Files
46 |
47 |
48 | Header Files
49 |
50 |
51 | Header Files
52 |
53 |
54 | Header Files
55 |
56 |
57 |
--------------------------------------------------------------------------------
/remove_pytube.cmd:
--------------------------------------------------------------------------------
1 | RD "%LOCALAPPDATA%\pytube-master" /S /Q
2 |
--------------------------------------------------------------------------------
/remove_youtube_transcript_api.cmd:
--------------------------------------------------------------------------------
1 | RD "%LOCALAPPDATA%\youtube-transcript-api-master" /S /Q
2 |
--------------------------------------------------------------------------------
/video/audioplayer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | struct IAudioPlayerCallback
6 | {
7 | virtual void AppendFrameClock(double frame_clock) = 0;
8 | };
9 |
10 | struct IAudioPlayer
11 | {
12 | virtual ~IAudioPlayer() = default;
13 | virtual void SetCallback(IAudioPlayerCallback* callback) = 0;
14 |
15 | virtual void InitializeThread() = 0;
16 | virtual void DeinitializeThread() = 0;
17 |
18 | virtual void Close() = 0;
19 | virtual bool Open(int bytesPerSample, int channels, int* samplesPerSec) = 0;
20 |
21 | virtual void SetVolume(double volume) = 0;
22 | virtual double GetVolume() const = 0;
23 |
24 | // stops playback on the given output device and resets the current position
25 | virtual void WaveOutReset() = 0;
26 | // pauses playback on the given output device
27 | virtual void WaveOutPause() = 0;
28 | // resumes playback on a paused output device
29 | virtual void WaveOutRestart() = 0;
30 |
31 | virtual bool WriteAudio(uint8_t* write_data, int64_t write_size) = 0;
32 | };
33 |
--------------------------------------------------------------------------------
/video/decoderiocontext.cpp:
--------------------------------------------------------------------------------
1 | #include "decoderiocontext.h"
2 |
3 | extern "C"
4 | {
5 | #include
6 | }
7 |
8 |
9 | // static
10 | int DecoderIOContext::IOReadFunc(void *data, uint8_t *buf, int buf_size)
11 | {
12 | auto *hctx = static_cast(data);
13 | try
14 | {
15 | auto len = hctx->stream->sgetn((char*)buf, buf_size);
16 | if (len <= 0)
17 | {
18 | // Let FFmpeg know that we have reached EOF, or do something else
19 | return AVERROR_EOF;
20 | }
21 | return static_cast(len);
22 | }
23 | catch (const std::exception&)
24 | {
25 | // Handle any exceptions that may occur during sgetn
26 | return AVERROR(EIO);
27 | }
28 | }
29 |
30 | // whence: SEEK_SET, SEEK_CUR, SEEK_END (like fseek) and AVSEEK_SIZE
31 | // static
32 | int64_t DecoderIOContext::IOSeekFunc(void *data, int64_t pos, int whence)
33 | {
34 | auto *hctx = static_cast(data);
35 |
36 | if (whence == AVSEEK_SIZE)
37 | {
38 | // return the file size if you wish to
39 | auto current = hctx->stream->pubseekoff(0, std::ios_base::cur, std::ios_base::in);
40 | auto result = hctx->stream->pubseekoff(0, std::ios_base::end, std::ios_base::in);
41 | hctx->stream->pubseekoff(current, std::ios_base::beg, std::ios_base::in);
42 | return result;
43 | }
44 |
45 | std::ios_base::seekdir dir;
46 | switch (whence)
47 | {
48 | case SEEK_SET:
49 | dir = std::ios_base::beg;
50 | break;
51 | case SEEK_CUR:
52 | dir = std::ios_base::cur;
53 | break;
54 | case SEEK_END:
55 | dir = std::ios_base::end;
56 | break;
57 | default:
58 | return -1LL;
59 | }
60 |
61 | return hctx->stream->pubseekoff(pos, dir);
62 | }
63 |
64 | DecoderIOContext::DecoderIOContext(std::unique_ptr s)
65 | : stream(std::move(s))
66 | {
67 | // allocate buffer
68 | bufferSize = 1024 * 64; // FIXME: not sure what size to use
69 | buffer = static_cast(av_malloc(bufferSize)); // see destructor for details
70 |
71 | // allocate the AVIOContext
72 | ioCtx =
73 | avio_alloc_context(buffer, bufferSize, // internal buffer and its size
74 | 0, // write flag (1=true,0=false)
75 | (void *)this, // user data, will be passed to our callback functions
76 | IOReadFunc,
77 | nullptr, // no writing
78 | IOSeekFunc);
79 | }
80 |
81 | DecoderIOContext::~DecoderIOContext()
82 | {
83 | //CHANNEL_LOG(ffmpeg_closing) << "In DecoderIOContext::~DecoderIOContext()";
84 |
85 | // NOTE: ffmpeg messes up the buffer
86 | // so free the buffer first then free the context
87 | av_free(ioCtx->buffer);
88 | ioCtx->buffer = nullptr;
89 | av_free(ioCtx);
90 | }
91 |
92 | void DecoderIOContext::initAVFormatContext(AVFormatContext *pCtx)
93 | {
94 | pCtx->pb = ioCtx;
95 | pCtx->flags |= AVFMT_FLAG_CUSTOM_IO;
96 |
97 | // you can specify a format directly
98 | // pCtx->iformat = av_find_input_format("h264");
99 |
100 | // or read some of the file and let ffmpeg do the guessing
101 | auto len = stream->sgetn((char *)buffer, bufferSize);
102 | if (len <= 0)
103 | {
104 | return;
105 | }
106 | // reset to beginning of file
107 | stream->pubseekoff(0, std::ios_base::beg, std::ios_base::in);
108 |
109 | AVProbeData probeData = {nullptr};
110 | probeData.buf = buffer;
111 | probeData.buf_size = bufferSize - 1;
112 | probeData.filename = "";
113 | pCtx->iformat = av_probe_input_format(&probeData, 1);
114 | }
115 |
--------------------------------------------------------------------------------
/video/decoderiocontext.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | struct AVIOContext;
8 | struct AVFormatContext;
9 |
10 | class DecoderIOContext
11 | {
12 | private:
13 | AVIOContext *ioCtx;
14 | uint8_t *buffer; // internal buffer for ffmpeg
15 | int bufferSize;
16 | std::unique_ptr stream;
17 |
18 | public:
19 | DecoderIOContext(std::unique_ptr s);
20 | ~DecoderIOContext();
21 |
22 | void initAVFormatContext(AVFormatContext * /*pCtx*/);
23 |
24 | static int IOReadFunc(void *data, uint8_t *buf, int buf_size);
25 | static int64_t IOSeekFunc(void *data, int64_t pos, int whence);
26 | };
27 |
--------------------------------------------------------------------------------
/video/displayrunnable.cpp:
--------------------------------------------------------------------------------
1 | #include "ffmpegdecoder.h"
2 |
3 | #include
4 |
5 | void FFmpegDecoder::displayRunnable()
6 | {
7 | CHANNEL_LOG(ffmpeg_threads) << "Displaying thread started";
8 |
9 | #ifdef TRACE_DELAY_STATS
10 | double sumIndications = 0;
11 | double sqSumIndications = 0;
12 |
13 | enum { MAX_INDICATIONS = 200 };
14 | int numIndications = 0;
15 | #endif
16 |
17 | while (!boost::this_thread::interruption_requested())
18 | {
19 | {
20 | boost::unique_lock locker(m_videoFramesMutex);
21 | m_videoFramesCV.wait(locker, [this]()
22 | {
23 | return !m_frameDisplayingRequested &&
24 | m_videoFramesQueue.canPop();
25 | });
26 | }
27 |
28 | VideoFrame& current_frame = m_videoFramesQueue.front();
29 | m_frameDisplayingRequested = true;
30 |
31 | if (current_frame.m_convert.valid() && !current_frame.m_convert.get()) {
32 | finishedDisplayingFrame(m_generation);
33 | continue;
34 | }
35 |
36 | assert(m_videoStartClock != VIDEO_START_CLOCK_NOT_INITIALIZED);
37 |
38 | // Frame skip
39 | if (!m_videoFramesQueue.canPush()
40 | && m_videoStartClock + current_frame.m_pts < GetHiResTime())
41 | {
42 | CHANNEL_LOG(ffmpeg_threads) << __FUNCTION__ << " Framedrop";
43 | finishedDisplayingFrame(m_generation);
44 | continue;
45 | }
46 |
47 | const auto pts = current_frame.m_pts;
48 | const auto duration = current_frame.m_duration;
49 |
50 | // Possibly give it time to render frame
51 | if (m_frameListener != nullptr)
52 | {
53 | m_frameListener->updateFrame(this, m_generation);
54 | }
55 |
56 | const auto speed = getSpeedRational();
57 |
58 | for (;;)
59 | {
60 | const double delay = m_videoStartClock + pts - GetHiResTime();
61 | if (delay < 0.005) {
62 | break;
63 | }
64 | if (delay > 0.1)
65 | {
66 | boost::this_thread::sleep_for(
67 | boost::chrono::milliseconds(100 * speed.denominator / speed.numerator));
68 | continue;
69 | }
70 |
71 | boost::this_thread::sleep_for(
72 | boost::chrono::milliseconds(int(delay * 1000. * speed.denominator / speed.numerator)));
73 | break;
74 | }
75 |
76 | // It's time to display converted frame
77 | if (duration != AV_NOPTS_VALUE)
78 | {
79 | m_currentTime = duration;
80 | if ((m_decoderListener != nullptr) && m_seekDuration == AV_NOPTS_VALUE)
81 | {
82 | m_decoderListener->changedFramePosition(
83 | m_startTime,
84 | duration,
85 | m_duration + m_startTime);
86 | }
87 | }
88 |
89 | #ifdef TRACE_DELAY_STATS
90 | const double delay = m_videoStartClock + pts - GetHiResTime();
91 | sumIndications += delay;
92 | sqSumIndications += delay * delay;
93 | if (++numIndications >= MAX_INDICATIONS)
94 | {
95 | const double avg = sumIndications / numIndications;
96 | CHANNEL_LOG(ffmpeg_threads) << "Average frame delay: " << avg
97 | << "; frame delay deviation: " << sqrt(sqSumIndications / numIndications - avg * avg);
98 | sumIndications = 0;
99 | sqSumIndications = 0;
100 | numIndications = 0;
101 | }
102 | #endif
103 |
104 | if (m_frameListener != nullptr)
105 | {
106 | m_frameListener->drawFrame(this, m_generation);
107 | }
108 | else
109 | {
110 | finishedDisplayingFrame(m_generation);
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/video/ffmpeg_dxva2.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | * This file is part of FFmpeg.
5 | *
6 | * FFmpeg is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * FFmpeg 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 GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with FFmpeg; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #ifdef _WIN32
22 |
23 | typedef struct AVCodecContext AVCodecContext;
24 | typedef struct AVFrame AVFrame;
25 |
26 | typedef struct IDirect3DDevice9 IDirect3DDevice9;
27 | typedef struct IDirect3DSurface9 IDirect3DSurface9;
28 |
29 | int dxva2_init(AVCodecContext *s);
30 | void dxva2_uninit(void* ist);
31 | int dxva2_convert_data(IDirect3DSurface9* surface, AVFrame *tmp_frame, int width, int height);
32 | int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame);
33 |
34 | IDirect3DDevice9* get_device(AVCodecContext *s);
35 |
36 | #endif // _WIN32
37 |
--------------------------------------------------------------------------------
/video/fqueue.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include