evan.liu d0074858bf CAIIC 定制版 v1.0.0:英文默认界面、2K/4K 支持、集成抠图插件、更换品牌图标
界面与品牌
- 默认 UI 语言固定为英文,不再跟随系统区域设置自动切换(frontend/OBSApp.cpp),用户仍可在设置中手动切换
- 程序图标更换为 CAIIC logo:exe 图标 obs-studio.ico 及界面/托盘/About 图标 obs.png
- About 窗口精简为 logo + 名称 + 版本号,移除项目介绍、赞助名单、Authors/License 标签页
- 版本号定为 1.0.0(构建参数 OBS_VERSION_OVERRIDE=1.0.0)

分辨率支持
- 移除首次启动将画布强制限制为 1920x1080 的逻辑,默认使用显示器原生分辨率
- 设置-视频 与自动配置向导新增 3840x2160 / 2560x1440 预设
- 自动配置向导性能测试上限放宽至 4K60(软硬件编码数据率上限及起始分辨率钳制)

插件
- 集成 obs-shaderfilter 2.6.0(绿幕抠图/自定义着色器滤镜),并适配新版 libobs 的 gs_image_file_ex API
- 补齐缺失的源码:obs-browser、obs-websocket、libdshowcapture(含 external/capture-device-support)

工程
- 新增 .gitignore,排除 deploy/ 发布目录与构建日志
2026-09-18 20:41:13 +08:00

307 lines
6.1 KiB
C++

/*
* Copyright (C) 2023 Lain Bailey <lain@obsproject.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/
#pragma once
#include <vector>
#include <string>
#include <functional>
#ifdef DSHOWCAPTURE_EXPORTS
#define DSHOWCAPTURE_EXPORT __declspec(dllexport)
#else
#define DSHOWCAPTURE_EXPORT
#endif
#define DSHOWCAPTURE_VERSION_MAJOR 0
#define DSHOWCAPTURE_VERSION_MINOR 10
#define DSHOWCAPTURE_VERSION_PATCH 0
#define MAKE_DSHOWCAPTURE_VERSION(major, minor, patch) \
((major << 24) | (minor << 16) | (patch))
#define DSHOWCAPTURE_VERSION \
MAKE_DSHOWCAPTURE_VERSION(DSHOWCAPTURE_VERSION_MAJOR, \
DSHOWCAPTURE_VERSION_MINOR, \
DSHOWCAPTURE_VERSION_PATCH)
#define DSHOW_MAX_PLANES 8
namespace DShow {
/* internal forward */
struct HDevice;
struct HVideoEncoder;
struct VideoConfig;
struct AudioConfig;
typedef std::function<void(const VideoConfig &config, unsigned char *data,
size_t size, long long startTime, long long stopTime,
long rotation)>
VideoProc;
typedef std::function<void(const AudioConfig &config, unsigned char *data,
size_t size, long long startTime, long long stopTime)>
AudioProc;
typedef std::function<void()> ReactivateProc;
enum class InitGraph {
False,
True,
};
/** DirectShow configuration dialog type */
enum class DialogType {
ConfigVideo,
ConfigAudio,
ConfigCrossbar,
ConfigCrossbar2,
};
enum class VideoFormat {
Any,
Unknown,
/* raw formats */
ARGB = 100,
XRGB,
RGB24,
/* planar YUV formats */
I420 = 200,
NV12,
YV12,
Y800,
P010,
/* packed YUV formats */
YVYU = 300,
YUY2,
UYVY,
HDYC,
/* encoded formats */
MJPEG = 400,
H264,
HEVC,
};
enum class AudioFormat {
Any,
Unknown,
/* raw formats */
Wave16bit = 100,
WaveFloat,
/* encoded formats */
AAC = 200,
AC3,
MPGA, /* MPEG 1 */
};
enum class AudioMode {
Capture,
DirectSound,
WaveOut,
};
enum class Result {
Success,
InUse,
Error,
};
struct VideoInfo {
int minCX, minCY;
int maxCX, maxCY;
int granularityCX, granularityCY;
long long minInterval, maxInterval;
VideoFormat format;
};
struct AudioInfo {
int minChannels, maxChannels;
int channelsGranularity;
int minSampleRate, maxSampleRate;
int sampleRateGranularity;
AudioFormat format;
};
struct DeviceId {
std::wstring name;
std::wstring path;
};
struct VideoDevice : DeviceId {
bool audioAttached = false;
bool separateAudioFilter = false;
std::vector<VideoInfo> caps;
};
struct AudioDevice : DeviceId {
std::vector<AudioInfo> caps;
};
struct Config : DeviceId {
/** Use the device's desired default config */
bool useDefaultConfig = true;
};
struct VideoConfig : Config {
VideoProc callback;
ReactivateProc reactivateCallback;
/** Desired width/height of video. */
int cx = 0, cy_abs = 0;
/** Whether or not cy was negative. */
bool cy_flip = false;
/** Desired frame interval (in 100-nanosecond units) */
long long frameInterval = 0;
/** Internal video format. */
VideoFormat internalFormat = VideoFormat::Any;
/** Desired video format. */
VideoFormat format = VideoFormat::Any;
};
struct AudioConfig : Config {
AudioProc callback;
/**
* Use the audio attached to the video device
*
* (name/path member variables will be ignored)
*/
bool useVideoDevice = false;
/** Use separate filter for audio */
bool useSeparateAudioFilter = false;
/** Desired sample rate */
int sampleRate = 0;
/** Desired channels */
int channels = 0;
/** Desired audio format */
AudioFormat format = AudioFormat::Any;
/** Audio playback mode */
AudioMode mode = AudioMode::Capture;
/** Desired buffer */
int buffer = 0;
};
class DSHOWCAPTURE_EXPORT Device {
HDevice *context;
public:
Device(InitGraph initialize = InitGraph::False);
~Device();
bool Valid() const;
bool ResetGraph();
void ShutdownGraph();
bool SetVideoConfig(VideoConfig *config);
bool SetAudioConfig(AudioConfig *config);
/**
* Connects all the configured filters together.
*
* Call SetVideoConfig and/or SetAudioConfig before using.
*/
bool ConnectFilters();
Result Start();
void Stop();
bool GetVideoConfig(VideoConfig &config) const;
bool GetAudioConfig(AudioConfig &config) const;
bool GetVideoDeviceId(DeviceId &id) const;
bool GetAudioDeviceId(DeviceId &id) const;
/**
* Opens a DirectShow dialog associated with this device
*
* @param type The dialog type
*/
void OpenDialog(void *hwnd, DialogType type) const;
static bool EnumVideoDevices(std::vector<VideoDevice> &devices);
static bool EnumAudioDevices(std::vector<AudioDevice> &devices);
};
struct VideoEncoderConfig : DeviceId {
int fpsNumerator;
int fpsDenominator;
int bitrate;
int keyframeInterval;
int cx;
int cy;
};
struct EncoderPacket {
unsigned char *data;
size_t size;
long long pts;
long long dts;
};
class VideoEncoder {
HVideoEncoder *context;
public:
VideoEncoder();
~VideoEncoder();
bool Valid() const;
bool Active() const;
bool ResetGraph();
bool SetConfig(VideoEncoderConfig &config);
bool GetConfig(VideoEncoderConfig &config) const;
bool Encode(unsigned char *data[DSHOW_MAX_PLANES],
size_t linesize[DSHOW_MAX_PLANES], long long timestampStart,
long long timestampEnd, EncoderPacket &packet,
bool &new_packet);
static bool EnumEncoders(std::vector<DeviceId> &encoders);
};
enum class LogType {
Error,
Warning,
Info,
Debug,
};
typedef void (*LogCallback)(LogType type, const wchar_t *msg, void *param);
DSHOWCAPTURE_EXPORT void SetLogCallback(LogCallback callback, void *param);
};