├── .gitignore ├── Define.h ├── LICENSE ├── README.md ├── ReadMe.txt ├── core-info.h ├── demo.py ├── func-draw.h ├── func.h ├── libcore-internal.h ├── libcore.cpp ├── libcore.h ├── libcore.vcxproj ├── libcore.vcxproj.filters └── libcore.vcxproj.user /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /Define.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "obs.h" 4 | 5 | #include 6 | 7 | 8 | #define TEXT_WINDOW_CAPTURE obs_module_text("WindowCapture") 9 | #define TEXT_WINDOW obs_module_text("WindowCapture.Window") 10 | #define TEXT_MATCH_PRIORITY obs_module_text("WindowCapture.Priority") 11 | #define TEXT_MATCH_TITLE obs_module_text("WindowCapture.Priority.Title") 12 | #define TEXT_MATCH_CLASS obs_module_text("WindowCapture.Priority.Class") 13 | #define TEXT_MATCH_EXE obs_module_text("WindowCapture.Priority.Exe") 14 | #define TEXT_CAPTURE_CURSOR obs_module_text("CaptureCursor") 15 | #define TEXT_COMPATIBILITY obs_module_text("Compatibility") 16 | 17 | #define INPUT_AUDIO_SOURCE "wasapi_input_capture" 18 | #define OUTPUT_AUDIO_SOURCE "wasapi_output_capture" 19 | 20 | #define TEXT_OUTPUT_AUDIO_DEFAULT_DEVICE_ID "default" 21 | #define TEXT_OUTPUT_AUDIO_DEFAULT_DEVICE_DESC "DesktopAudioDevice1" 22 | #define TEXT_INPUT_AUDIO_DEFAULT_DEVICE_ID "default" 23 | #define TEXT_INPUT_AUDIO_DEFAULT_DEVICE_DESC "AuxAudioDevice1" 24 | 25 | #define TEXT_FILTER_NOISE "noise_gate_name" 26 | #define TEXT_FILTER_NOISE_ID "noise_gate_filter" 27 | 28 | #define S_OPEN_THRESHOLD "open_threshold" 29 | #define S_CLOSE_THRESHOLD "close_threshold" 30 | #define S_ATTACK_TIME "attack_time" 31 | #define S_HOLD_TIME "hold_time" 32 | #define S_RELEASE_TIME "release_time" 33 | 34 | 35 | #define PREVIEW_EDGE_SIZE 10 36 | 37 | /* --------------------------------------------------- */ 38 | 39 | typedef obs_source_t* SourceContext; 40 | typedef obs_scene_t* SceneContext; 41 | typedef obs_display_t* DisplayContext; 42 | typedef obs_properties_t* SourcePorperty; 43 | typedef obs_sceneitem_t * SceneItem; 44 | 45 | obs_service_t * service = nullptr; 46 | obs_data_t *h264Settings = nullptr; 47 | obs_data_t *aacSettings = nullptr; 48 | 49 | //rtmp 50 | obs_encoder_t *h264Streaming = nullptr; 51 | obs_encoder_t *aacStreaming = nullptr; 52 | obs_output_t* streamOutput = nullptr; 53 | 54 | //record 55 | obs_encoder_t *aacRecording = nullptr; 56 | obs_encoder_t *h264Recording = nullptr; 57 | obs_output_t* fileOutput = nullptr; 58 | 59 | static bool firstStart = true; 60 | 61 | static int preview_wnd_width = 800; 62 | static int preview_wnd_height = 600; 63 | 64 | static float preview_wnd_scale = 0.0; 65 | 66 | static int preview_wnd_x = 0; 67 | static int preview_wnd_y = 0; 68 | 69 | static uint64_t lastBytesSent = 0; 70 | static uint64_t lastBytesSentTime = 0; 71 | static uint64_t beginBytesSend = 0; 72 | 73 | static uint64_t lastTotalFrames = 0; 74 | 75 | 76 | //static const int cx = 800; 77 | //static const int cy = 600; 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 sesame 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # obs-studio-simply-c-sdk 2 | 本项目是基于obs-studio开源项目 3 | 并对其中的libobs代码进行二次开发并封装的c接口的sdk 4 | 这是上传的还是去年七月份写的测试代码, 5 | 6 | 将于近期更新为去年11月份的代码, 7 | 后来由于忙于另外一个python项目, 8 | 所以到现在也没再去更新, 9 | 不过接下来将会花时间打算好好完善它。 10 | 11 | 写这个的起因,是因为打算基于obs做款游戏直播软件, 12 | 但是obs studio的libobs不太好用, 13 | 过于繁杂,故打算在其基础上重新写个c的dll, 来封装它。 14 | 再自己另用qt写个界面,调用自己的c sdk. 15 | 16 | 这个项目是基于vs2013, 在网上下载的obs studio的项目中里,添加进此项目。 17 | 原来的obs studio是由cmake生成vs2013下的工程。 18 | 生成的工程属性中,路径都是硬编码,所以我这个项目中暂时也是的硬编码。 19 | 所以现在这个项目是无法正常编译的,你需要自己去修改这个项目的工程属性。 20 | 后续我会慢慢改进。 21 | 22 | 最近由于工作忙,抱歉。 23 | 但是或许忙有的时候也只是借口:( 24 | 25 | 上传此项目的目的,也希望那些和我一样,需要基于obs studio做二次开发的人,能节省的时间,更快的了解如何学习使用obs studio进行二次开发。 26 | 少走点我走过的弯路,也就值得了。 27 | 28 | 我本人比较菜,也不擅长写sdk, 献丑了。 29 | 30 | 2017/2/22 31 | 32 | > 如果一件事情,能使别人受益,那就值得去做。不是么。共勉... 33 | > 34 | > 一粒小芝麻 35 | > 36 | > purpledaisy@163.com 37 | > 38 | > [purpledaisy.cn](http://purpledaisy.cn/) 39 | 40 | ---------------------------------------------------------------- 41 | update 2020.9.24 42 | 这个项目的主要代码都是2016年写的。 43 | 当时obs studio的资料还比较少。 44 | 还记得当时obs的官网上,官方说的obs很简单的,看代码就好了。当时看到这个回复,有点哭笑不得。 45 | 四年过去了,现在obs的网上资料也多了很多。 46 | 不过这半年里,也偶有些朋友来问我这个项目的事情, 47 | 没想到还能帮助到一些人。 48 | 49 | 这个项目暂时没有更新的打算了。 50 | 基本功能也都具备,可以用于作为obs开发的入门学习。 51 | 今天上传了一个当时写的demo.py. 52 | 53 | ----------------------------- 54 | 2023.8.25

55 | 56 | ```diff 57 | !keep fukushima radioactive water on the ground 58 | 59 | -------------------------------------------------------------------------------- /ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | 动态链接库:libcore 项目概述 3 | ======================================================================== 4 | 5 | 应用程序向导已为您创建了此 libcore DLL。 6 | 7 | 本文件概要介绍组成 libcore 应用程序的每个文件的内容。 8 | 9 | 10 | libcore.vcxproj 11 | 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 12 | 13 | libcore.vcxproj.filters 14 | 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 15 | 16 | libcore.cpp 17 | 这是主 DLL 源文件。 18 | 19 | ///////////////////////////////////////////////////////////////////////////// 20 | 其他标准文件: 21 | 22 | StdAfx.h, StdAfx.cpp 23 | 这些文件用于生成名为 libcore.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 24 | 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 其他注释: 27 | 28 | 应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 29 | 30 | ///////////////////////////////////////////////////////////////////////////// 31 | -------------------------------------------------------------------------------- /core-info.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tristsesame/obs-studio-simply-c-sdk/6a9eb366889ca9bf7ecb96cc6f1c9cdb14bdcc27/core-info.h -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import sys 4 | sys.path.append(u"../") 5 | #sys.path.append(u"obs-plugins/32bit/") 6 | from win32gui import * 7 | from _ctypes import byref 8 | from ctypes import pythonapi, c_void_p, py_object 9 | from Common.CXCommon import * 10 | from Common.ErrorLogger import * 11 | import ctypes, sys, time, traceback,os 12 | from PySide.QtCore import * 13 | from PySide.QtGui import * 14 | 15 | def cur_file_dir(): 16 | #获取脚本路径 17 | path = sys.path[0] 18 | #判断为脚本文件还是py2exe编译后的文件,如果是脚本文件,则返回的是脚本的目录,如果是py2exe编译后的文件,则返回的是编译后的文件路径 19 | if os.path.isdir(path): 20 | return path 21 | elif os.path.isfile(path): 22 | return os.path.dirname(path) 23 | #打印结果 24 | curr_dir_before = cur_file_dir() 25 | 26 | class LibCore(object): 27 | def __init__(self): 28 | try: 29 | self.__obs = ctypes.CDLL("libcore.dll") 30 | ctypes.CDLL("obs-plugins/32bit/obs-ffmpeg.dll") 31 | ctypes.CDLL("obs-plugins/32bit/rtmp-services.dll") 32 | #ctypes.CDLL("../../obs-plugins.bak/32bit/win-capture.dll") 33 | #ctypes.CDLL("../../obs-plugins.bak/32bit/win-dshow.dll") 34 | except Exception as inst: 35 | self.__log(inst) 36 | 37 | def __log(self,inst): 38 | errlogger.write(inst, traceback) 39 | 40 | def init(self): 41 | try: 42 | return self.__obs.core_init() 43 | except Exception as inst: 44 | self.__log(inst) 45 | 46 | def uninit(self): 47 | try: 48 | return self.__obs.core_uninit() 49 | except Exception as inst: 50 | self.__log(inst) 51 | 52 | 53 | def init_scene(self): 54 | try: 55 | self.__obs.core_init_scene() 56 | except Exception as inst: 57 | self.__log(inst) 58 | 59 | def set_video(self,hwnd,output_width,output_height): 60 | try: 61 | pythonapi.PyCObject_AsVoidPtr.restype = c_void_p 62 | pythonapi.PyCObject_AsVoidPtr.argtypes = [ py_object ] 63 | hwnd = pythonapi.PyCObject_AsVoidPtr(hwnd) 64 | print "hwnd:", hwnd 65 | return self.__obs.core_set_video(hwnd,output_width,output_height) 66 | except Exception as inst: 67 | self.__log(inst) 68 | 69 | def set_audio(self): 70 | try: 71 | self.__obs.core_set_audio() 72 | except Exception as inst: 73 | self.__log(inst) 74 | 75 | def load_audio(self): 76 | try: 77 | self.__obs.core_load_audio() 78 | except Exception as inst: 79 | self.__log(inst) 80 | 81 | def add_moudles_path(self,bin,data): 82 | try: 83 | self.__obs.core_add_moudles_path(bin,data) 84 | except Exception as inst: 85 | self.__log(inst) 86 | 87 | def load_all_modules(self): 88 | try: 89 | self.__obs.core_load_all_modules() 90 | except Exception as inst: 91 | self.__log(inst) 92 | 93 | def create_win_capture_source(self): 94 | try: 95 | self.__obs.core_create_win_capture_source.restype = ctypes.c_bool 96 | return self.__obs.core_create_win_capture_source() 97 | except Exception as inst: 98 | self.__log(inst) 99 | 100 | def get_win_nums(self): 101 | try: 102 | return self.__obs.core_get_win_nums() 103 | except Exception as inst: 104 | self.__log(inst) 105 | 106 | 107 | def get_win_name(self,index): 108 | try: 109 | self.__obs.core_get_win_name.restype = ctypes.c_char_p 110 | return self.__obs.core_get_win_name(index) 111 | except Exception as inst: 112 | self.__log(inst) 113 | 114 | 115 | def set_win_capture_source(self,index): 116 | try: 117 | return self.__obs.core_set_win_capture_source(index) 118 | except Exception as inst: 119 | self.__log(inst) 120 | 121 | def create_dshow_source(self): 122 | try: 123 | self.__obs.core_create_dshow_source.restype = ctypes.c_bool 124 | return self.__obs.core_create_dshow_source() 125 | except Exception as inst: 126 | self.__log(inst) 127 | 128 | def get_cam_nums(self): 129 | try: 130 | return self.__obs.core_get_cam_nums() 131 | except Exception as inst: 132 | self.__log(inst) 133 | 134 | 135 | def get_cam_name(self,index): 136 | try: 137 | self.__obs.core_get_cam_name.restype = ctypes.c_char_p 138 | return self.__obs.core_get_cam_name(index) 139 | except Exception as inst: 140 | self.__log(inst) 141 | 142 | 143 | def set_dshow_source(self,index): 144 | try: 145 | return self.__obs.core_set_dshow_source(index) 146 | except Exception as inst: 147 | self.__log(inst) 148 | 149 | 150 | def init_stream(self): 151 | try: 152 | self.__obs.core_init_stream() 153 | except Exception as inst: 154 | self.__log(inst) 155 | 156 | 157 | def start_stream(self,rtmp_url,video_bit_rate,audio_bit_rate): 158 | try: 159 | self.__obs.core_start_stream(rtmp_url,video_bit_rate,audio_bit_rate) 160 | except Exception as inst: 161 | self.__log(inst) 162 | 163 | 164 | if __name__ == "__main__": 165 | #set hwnd 166 | # Create a Qt application 167 | app = QApplication(sys.argv) 168 | # Create a Label and show it 169 | preview = QWidget() 170 | 171 | 172 | obs = LibCore() 173 | print obs.init() 174 | print GetCurrentFileDir() 175 | 176 | obs.set_audio() 177 | hwnd = preview.winId() 178 | k = obs.set_video(hwnd,1920,1080) 179 | print "set_video:" , k 180 | 181 | #obs.add_moudles_path("F:/GitWork/YBGameDemo/obs-plugins/32bit", "F:/GitWork/testDemo/data/%module%") 182 | obs.add_moudles_path("F:\\GitWork\\testDemo\\obs-plugins\\32bit", "F:\\GitWork\\testDemo\\data\\obs-plugins\\%module%") 183 | obs.load_all_modules() 184 | 185 | print " " 186 | print "**************************" 187 | obs.init_stream() 188 | obs.load_audio() 189 | 190 | print obs.create_win_capture_source() 191 | k = obs.get_win_nums() 192 | for i in range(k): 193 | print i,"->",obs.get_win_name(i) 194 | print "**************************" 195 | print obs.set_win_capture_source(0) 196 | print "**************************" 197 | 198 | 199 | print obs.create_dshow_source() 200 | k = obs.get_cam_nums() 201 | for i in range(k): 202 | print i, "->", obs.get_cam_name(i) 203 | print "**************************" 204 | print obs.set_dshow_source(2) 205 | print "**************************" 206 | 207 | obs.init_scene() 208 | obs.start_stream("rtmp://liveup-rtmp.xxx.xxx/stream/108", 2500, 160) 209 | #print qtv.GetDefaultAudioDeviceName() 210 | 211 | preview.show() 212 | # Enter Qt application main loop 213 | app.exec_() 214 | 215 | print obs.uninit() 216 | sys.exit() 217 | 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /func-draw.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "Define.h" 21 | 22 | #define HANDLE_RADIUS 4.0f 23 | #define HANDLE_SEL_RADIUS (HANDLE_RADIUS * 1.5f) 24 | 25 | gs_vertbuffer_t *gs_box = nullptr; 26 | gs_vertbuffer_t *gs_boxLeft = nullptr; 27 | gs_vertbuffer_t *gs_boxTop = nullptr; 28 | gs_vertbuffer_t *gs_boxRight = nullptr; 29 | gs_vertbuffer_t *gs_boxBottom = nullptr; 30 | gs_vertbuffer_t *gs_circle = nullptr; 31 | 32 | void InitPrimitives() 33 | { 34 | 35 | obs_enter_graphics(); 36 | 37 | gs_render_start(true); 38 | gs_vertex2f(0.0f, 0.0f); 39 | gs_vertex2f(0.0f, 1.0f); 40 | gs_vertex2f(1.0f, 1.0f); 41 | gs_vertex2f(1.0f, 0.0f); 42 | gs_vertex2f(0.0f, 0.0f); 43 | gs_box = gs_render_save(); 44 | 45 | gs_render_start(true); 46 | gs_vertex2f(0.0f, 0.0f); 47 | gs_vertex2f(0.0f, 1.0f); 48 | gs_boxLeft = gs_render_save(); 49 | 50 | gs_render_start(true); 51 | gs_vertex2f(0.0f, 0.0f); 52 | gs_vertex2f(1.0f, 0.0f); 53 | gs_boxTop = gs_render_save(); 54 | 55 | gs_render_start(true); 56 | gs_vertex2f(1.0f, 0.0f); 57 | gs_vertex2f(1.0f, 1.0f); 58 | gs_boxRight = gs_render_save(); 59 | 60 | gs_render_start(true); 61 | gs_vertex2f(0.0f, 1.0f); 62 | gs_vertex2f(1.0f, 1.0f); 63 | gs_boxBottom = gs_render_save(); 64 | 65 | gs_render_start(true); 66 | for (int i = 0; i <= 360; i += (360 / 20)) { 67 | float pos = RAD(float(i)); 68 | gs_vertex2f(cosf(pos), sinf(pos)); 69 | } 70 | gs_circle = gs_render_save(); 71 | 72 | obs_leave_graphics(); 73 | } 74 | 75 | static void DrawCircleAtPos(float x, float y, matrix4 &matrix, 76 | float previewScale) 77 | { 78 | struct vec3 pos; 79 | vec3_set(&pos, x, y, 0.0f); 80 | vec3_transform(&pos, &pos, &matrix); 81 | vec3_mulf(&pos, &pos, previewScale); 82 | 83 | gs_matrix_push(); 84 | gs_matrix_translate(&pos); 85 | gs_matrix_scale3f(HANDLE_RADIUS, HANDLE_RADIUS, 1.0f); 86 | gs_draw(GS_LINESTRIP, 0, 0); 87 | gs_matrix_pop(); 88 | } 89 | 90 | static inline bool crop_enabled(const obs_sceneitem_crop *crop) 91 | { 92 | return crop->left > 0 || 93 | crop->top > 0 || 94 | crop->right > 0 || 95 | crop->bottom > 0; 96 | } 97 | 98 | static bool CloseFloat(float a, float b, float epsilon = 0.01) 99 | { 100 | using std::abs; 101 | return abs(a - b) <= epsilon; 102 | } 103 | 104 | //static bool DrawSelectedItem(obs_sceneitem_t *item, int x, int y, int width, int height) 105 | static bool DrawSelectedItem(obs_scene_t *scene,obs_sceneitem_t *item, void *param) 106 | { 107 | if (!obs_sceneitem_selected(item)) 108 | return true; 109 | 110 | matrix4 boxTransform; 111 | matrix4 invBoxTransform; 112 | obs_sceneitem_get_box_transform(item, &boxTransform); 113 | matrix4_inv(&invBoxTransform, &boxTransform); 114 | 115 | vec3 bounds[] = { 116 | { { { 0.f, 0.f, 0.f } } }, 117 | { { { 1.f, 0.f, 0.f } } }, 118 | { { { 0.f, 1.f, 0.f } } }, 119 | { { { 1.f, 1.f, 0.f } } }, 120 | }; 121 | 122 | bool visible = std::all_of(std::begin(bounds), std::end(bounds), 123 | [&](const vec3 &b) 124 | { 125 | vec3 pos; 126 | vec3_transform(&pos, &b, &boxTransform); 127 | vec3_transform(&pos, &pos, &invBoxTransform); 128 | return CloseFloat(pos.x, b.x) && CloseFloat(pos.y, b.y); 129 | }); 130 | 131 | if (!visible) 132 | return true; 133 | 134 | obs_transform_info info; 135 | obs_sceneitem_get_info(item, &info); 136 | 137 | gs_load_vertexbuffer(gs_circle); 138 | 139 | float previewScale = preview_wnd_scale; 140 | 141 | DrawCircleAtPos(0.0f, 0.0f, boxTransform, previewScale); 142 | DrawCircleAtPos(0.0f, 1.0f, boxTransform, previewScale); 143 | DrawCircleAtPos(1.0f, 0.0f, boxTransform, previewScale); 144 | DrawCircleAtPos(1.0f, 1.0f, boxTransform, previewScale); 145 | DrawCircleAtPos(0.5f, 0.0f, boxTransform, previewScale); 146 | DrawCircleAtPos(0.0f, 0.5f, boxTransform, previewScale); 147 | DrawCircleAtPos(0.5f, 1.0f, boxTransform, previewScale); 148 | DrawCircleAtPos(1.0f, 0.5f, boxTransform, previewScale); 149 | 150 | gs_matrix_push(); 151 | gs_matrix_scale3f(previewScale, previewScale, 1.0f); 152 | gs_matrix_mul(&boxTransform); 153 | 154 | obs_sceneitem_crop crop; 155 | obs_sceneitem_get_crop(item, &crop); 156 | 157 | if (info.bounds_type == OBS_BOUNDS_NONE && crop_enabled(&crop)) { 158 | vec4 color; 159 | gs_effect_t *eff = gs_get_effect(); 160 | gs_eparam_t *param = gs_effect_get_param_by_name(eff, "color"); 161 | 162 | #define DRAW_SIDE(side, vb) \ 163 | if (crop.side > 0) \ 164 | vec4_set(&color, 0.0f, 1.0f, 0.0f, 1.0f); \ 165 | else \ 166 | vec4_set(&color, 1.0f, 0.0f, 0.0f, 1.0f); \ 167 | gs_effect_set_vec4(param, &color); \ 168 | gs_load_vertexbuffer(vb); \ 169 | gs_draw(GS_LINESTRIP, 0, 0); 170 | 171 | DRAW_SIDE(left, gs_boxLeft); 172 | DRAW_SIDE(top, gs_boxTop); 173 | DRAW_SIDE(right, gs_boxRight); 174 | DRAW_SIDE(bottom, gs_boxBottom); 175 | #undef DRAW_SIDE 176 | } 177 | else { 178 | gs_load_vertexbuffer(gs_box); 179 | gs_draw(GS_LINESTRIP, 0, 0); 180 | } 181 | 182 | gs_matrix_pop(); 183 | 184 | return true; 185 | } 186 | 187 | static void DrawSceneEditing(SceneContext scene) 188 | { 189 | gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID); 190 | gs_technique_t *tech = gs_effect_get_technique(solid, "Solid"); 191 | 192 | vec4 color; 193 | vec4_set(&color, 1.0f, 0.0f, 0.0f, 1.0f); 194 | gs_effect_set_vec4(gs_effect_get_param_by_name(solid, "color"), &color); 195 | 196 | gs_technique_begin(tech); 197 | gs_technique_begin_pass(tech, 0); 198 | 199 | if (scene) 200 | obs_scene_enum_items(scene, DrawSelectedItem, nullptr); 201 | 202 | gs_load_vertexbuffer(nullptr); 203 | 204 | gs_technique_end_pass(tech); 205 | gs_technique_end(tech); 206 | } -------------------------------------------------------------------------------- /func.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "Define.h" 14 | #include "func-draw.h" 15 | 16 | #define MAKE_DSHOW_FPS(interval) (10000000LL/(interval)) 17 | #define MAKE_DSHOW_FRAME_INTERVAL(fps) (10000000LL / (fps) ) 18 | 19 | using namespace std; 20 | 21 | static DisplayContext CreateDisplay(HWND hwnd) 22 | { 23 | RECT rc; 24 | GetClientRect(hwnd, &rc); 25 | 26 | gs_init_data info = {}; 27 | info.cx = rc.right; 28 | info.cy = rc.bottom; 29 | info.format = GS_RGBA; 30 | info.zsformat = GS_ZS_NONE; 31 | info.window.hwnd = hwnd; 32 | 33 | return obs_display_create(&info); 34 | } 35 | 36 | 37 | 38 | /* --------------------------------------------------- */ 39 | static inline void GetScaleAndCenterPos( 40 | int baseCX, int baseCY, int windowCX, int windowCY, 41 | int &x, int &y, float &scale) 42 | { 43 | double windowAspect, baseAspect; 44 | int newCX, newCY; 45 | 46 | windowAspect = double(windowCX) / double(windowCY); 47 | baseAspect = double(baseCX) / double(baseCY); 48 | 49 | if (windowAspect > baseAspect) { 50 | scale = float(windowCY) / float(baseCY); 51 | newCX = int(double(windowCY) * baseAspect); 52 | newCY = windowCY; 53 | } 54 | else { 55 | scale = float(windowCX) / float(baseCX); 56 | newCX = windowCX; 57 | newCY = int(float(windowCX) / baseAspect); 58 | } 59 | 60 | x = windowCX / 2 - newCX / 2; 61 | y = windowCY / 2 - newCY / 2; 62 | } 63 | 64 | /* 65 | static void RenderWindow(void *data, uint32_t cx, uint32_t cy) 66 | { 67 | obs_video_info ovi; 68 | obs_get_video_info(&ovi); 69 | 70 | //preview_wnd_width = int(preview_wnd_scale * float(ovi.base_width)); 71 | //preview_wnd_height = int(preview_wnd_scale * float(ovi.base_height)); 72 | 73 | gs_viewport_push(); 74 | gs_projection_push(); 75 | 76 | gs_ortho(0.0f, float(ovi.base_width), 0.0f, float(ovi.base_height), 77 | -100.0f, 100.0f); 78 | 79 | gs_set_viewport(preview_wnd_x, preview_wnd_y, 80 | preview_wnd_width, preview_wnd_height); 81 | 82 | //obs_source_video_render(src); 83 | obs_render_main_view(); 84 | 85 | gs_load_vertexbuffer(nullptr); 86 | 87 | gs_projection_pop(); 88 | gs_viewport_pop(); 89 | 90 | SceneContext scene = (SceneContext)data; 91 | 92 | DrawSceneEditing(scene); 93 | } 94 | */ 95 | 96 | static bool IsObjNameExisted(std::vector< std::pair > vec_str, std::string str_name) 97 | { 98 | for (size_t i = 0; i < vec_str.size(); i++) 99 | { 100 | if (str_name == vec_str[i].first) 101 | return true; 102 | } 103 | return false; 104 | } 105 | 106 | static bool IsObjNameExisted(std::vector vec_str, std::string str_name) 107 | { 108 | for (size_t i = 0; i < vec_str.size(); i++) 109 | { 110 | if (str_name == vec_str[i]) 111 | return true; 112 | } 113 | return false; 114 | } 115 | 116 | 117 | string GenerateSpecifiedFilename(const char *extension, bool noSpace, 118 | const char *format) 119 | { 120 | time_t now = time(0); 121 | struct tm *cur_time; 122 | cur_time = localtime(&now); 123 | 124 | const size_t spec_count = 23; 125 | const char *spec[][2] = { 126 | { "%CCYY", "%Y" }, 127 | { "%YY", "%y" }, 128 | { "%MM", "%m" }, 129 | { "%DD", "%d" }, 130 | { "%hh", "%H" }, 131 | { "%mm", "%M" }, 132 | { "%ss", "%S" }, 133 | { "%%", "%%" }, 134 | 135 | { "%a", "" }, 136 | { "%A", "" }, 137 | { "%b", "" }, 138 | { "%B", "" }, 139 | { "%d", "" }, 140 | { "%H", "" }, 141 | { "%I", "" }, 142 | { "%m", "" }, 143 | { "%M", "" }, 144 | { "%p", "" }, 145 | { "%S", "" }, 146 | { "%y", "" }, 147 | { "%Y", "" }, 148 | { "%z", "" }, 149 | { "%Z", "" }, 150 | }; 151 | 152 | char convert[128] = {}; 153 | string sf = format; 154 | string c; 155 | size_t pos = 0, len; 156 | 157 | while (pos < sf.length()) { 158 | len = 0; 159 | for (size_t i = 0; i < spec_count && len == 0; i++) { 160 | 161 | if (sf.find(spec[i][0], pos) == pos) { 162 | if (strlen(spec[i][1])) 163 | strftime(convert, sizeof(convert), 164 | spec[i][1], cur_time); 165 | else 166 | strftime(convert, sizeof(convert), 167 | spec[i][0], cur_time); 168 | 169 | len = strlen(spec[i][0]); 170 | 171 | c = convert; 172 | if (c.length() && c.find_first_not_of(' ') != 173 | std::string::npos) 174 | sf.replace(pos, len, convert); 175 | } 176 | } 177 | 178 | if (len) 179 | pos += strlen(convert); 180 | else if (!len && sf.at(pos) == '%') 181 | sf.erase(pos, 1); 182 | else 183 | pos++; 184 | } 185 | 186 | if (noSpace) 187 | replace(sf.begin(), sf.end(), ' ', '_'); 188 | 189 | sf += '.'; 190 | sf += extension; 191 | 192 | return (sf.length() < 256) ? sf : sf.substr(0, 255); 193 | } -------------------------------------------------------------------------------- /libcore-internal.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tristsesame/obs-studio-simply-c-sdk/6a9eb366889ca9bf7ecb96cc6f1c9cdb14bdcc27/libcore-internal.h -------------------------------------------------------------------------------- /libcore.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tristsesame/obs-studio-simply-c-sdk/6a9eb366889ca9bf7ecb96cc6f1c9cdb14bdcc27/libcore.cpp -------------------------------------------------------------------------------- /libcore.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tristsesame/obs-studio-simply-c-sdk/6a9eb366889ca9bf7ecb96cc6f1c9cdb14bdcc27/libcore.h -------------------------------------------------------------------------------- /libcore.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {CF348184-C87A-495B-9349-D24F45465A59} 15 | Win32Proj 16 | libcore 17 | 18 | 19 | 20 | DynamicLibrary 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | DynamicLibrary 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | F:\tools\obs-studio-master\obs-studio-master\build\libcore\Debug\ 45 | 46 | 47 | false 48 | F:\tools\obs-studio-master\obs-studio-master\build\libcore\Release 49 | 50 | 51 | 52 | NotUsing 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBCORE_EXPORTS;DL_OPENGL="libobs-opengl.dll";DL_D3D9="";DL_D3D11="libobs-d3d11.dll";%(PreprocessorDefinitions) 56 | true 57 | F:\tools\obs-studio-master\obs-studio-master\build\obs;F:\tools\obs-studio-master\obs-studio-master\obs;F:\tools\obs-studio-master\obs-studio-master\libobs;F:\tools\obs-studio-master\dependency\include;F:\tools\obs-studio-master\obs-studio-master\build\config;F:\tools\obs-studio-master\obs-studio-master\deps\libff\.;C:\Qt\Qt5.6.0\5.6\msvc2013\include;C:\Qt\Qt5.6.0\5.6\msvc2013\include\QtWidgets;C:\Qt\Qt5.6.0\5.6\msvc2013\include\QtGui;C:\Qt\Qt5.6.0\5.6\msvc2013\include\QtCore;C:\Qt\Qt5.6.0\5.6\msvc2013\.\mkspecs\win32-msvc2013;%(AdditionalIncludeDirectories) 58 | CompileAsCpp 59 | Sync 60 | false 61 | false 62 | 63 | 64 | Windows 65 | true 66 | %(AdditionalLibraryDirectories) 67 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\libobs\Debug\obs.lib;..\deps\libff\Debug\libff.lib;C:\Qt\Qt5.6.0\5.6\msvc2013\lib\Qt5Widgetsd.lib;F:\tools\obs-studio-master\dependency\bin\libcurl.lib;F:\tools\obs-studio-master\dependency\bin\avcodec.lib;F:\tools\obs-studio-master\dependency\bin\avfilter.lib;F:\tools\obs-studio-master\dependency\bin\avdevice.lib;F:\tools\obs-studio-master\dependency\bin\avutil.lib;F:\tools\obs-studio-master\dependency\bin\swscale.lib;F:\tools\obs-studio-master\dependency\bin\avformat.lib;F:\tools\obs-studio-master\dependency\bin\swresample.lib;C:\Qt\Qt5.6.0\5.6\msvc2013\lib\Qt5Guid.lib;C:\Qt\Qt5.6.0\5.6\msvc2013\lib\Qt5Cored.lib;C:\Qt\Qt5.6.0\5.6\msvc2013\lib\qtmaind.lib;%(AdditionalDependencies) 68 | 69 | 70 | false 71 | 72 | 73 | 74 | 75 | Level3 76 | NotUsing 77 | MaxSpeed 78 | true 79 | true 80 | WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBCORE_EXPORTS;DL_OPENGL="libobs-opengl.dll";DL_D3D9="";DL_D3D11="libobs-d3d11.dll";%(PreprocessorDefinitions) 81 | true 82 | F:\tools\obs-studio-master\obs-studio-master\build\obs;F:\tools\obs-studio-master\obs-studio-master\obs;F:\tools\obs-studio-master\obs-studio-master\libobs;F:\tools\obs-studio-master\dependency\include;F:\tools\obs-studio-master\obs-studio-master\build\config;F:\tools\obs-studio-master\obs-studio-master\deps\libff\.;C:\Qt\Qt5.6.0\5.6\msvc2013\include;C:\Qt\Qt5.6.0\5.6\msvc2013\include\QtWidgets;C:\Qt\Qt5.6.0\5.6\msvc2013\include\QtGui;C:\Qt\Qt5.6.0\5.6\msvc2013\include\QtCore;C:\Qt\Qt5.6.0\5.6\msvc2013\.\mkspecs\win32-msvc2013;%(AdditionalIncludeDirectories) 83 | 84 | 85 | Windows 86 | false 87 | true 88 | true 89 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\libobs\Release\obs.lib;..\deps\libff\Release\libff.lib;C:\Qt\Qt5.6.0\5.6\msvc2013\lib\Qt5Widgetsd.lib;F:\tools\obs-studio-master\dependency\bin\libcurl.lib;F:\tools\obs-studio-master\dependency\bin\avcodec.lib;F:\tools\obs-studio-master\dependency\bin\avfilter.lib;F:\tools\obs-studio-master\dependency\bin\avdevice.lib;F:\tools\obs-studio-master\dependency\bin\avutil.lib;F:\tools\obs-studio-master\dependency\bin\swscale.lib;F:\tools\obs-studio-master\dependency\bin\avformat.lib;F:\tools\obs-studio-master\dependency\bin\swresample.lib;C:\Qt\Qt5.6.0\5.6\msvc2013\lib\Qt5Guid.lib;C:\Qt\Qt5.6.0\5.6\msvc2013\lib\Qt5Cored.lib;C:\Qt\Qt5.6.0\5.6\msvc2013\lib\qtmaind.lib;%(AdditionalDependencies) 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /libcore.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 | 头文件 23 | 24 | 25 | 头文件 26 | 27 | 28 | 头文件 29 | 30 | 31 | 头文件 32 | 33 | 34 | 头文件 35 | 36 | 37 | 头文件 38 | 39 | 40 | 41 | 42 | 源文件 43 | 44 | 45 | -------------------------------------------------------------------------------- /libcore.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------