界面与品牌 - 默认 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/ 发布目录与构建日志
307 lines
6.1 KiB
C++
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);
|
|
};
|