界面与品牌 - 默认 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/ 发布目录与构建日志
336 lines
7.7 KiB
C++
336 lines
7.7 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
|
|
*/
|
|
|
|
#include "dshow-formats.hpp"
|
|
#include "dshow-media-type.hpp"
|
|
|
|
#ifndef __MINGW32__
|
|
|
|
const GUID MEDIASUBTYPE_RAW_AAC1 = {0x000000FF,
|
|
0x0000,
|
|
0x0010,
|
|
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b,
|
|
0x71}};
|
|
|
|
const GUID MEDIASUBTYPE_I420 = {0x30323449,
|
|
0x0000,
|
|
0x0010,
|
|
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b,
|
|
0x71}};
|
|
|
|
const GUID MEDIASUBTYPE_DVM = {0x00002000,
|
|
0x0000,
|
|
0x0010,
|
|
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b,
|
|
0x71}};
|
|
|
|
#endif
|
|
|
|
const GUID MEDIASUBTYPE_Y800 = {0x30303859,
|
|
0x0000,
|
|
0x0010,
|
|
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b,
|
|
0x71}};
|
|
|
|
#ifdef ENABLE_HEVC
|
|
const GUID MEDIASUBTYPE_HEVC = {0x43564548,
|
|
0x0000,
|
|
0x0010,
|
|
{0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b,
|
|
0x71}};
|
|
#endif
|
|
|
|
namespace DShow {
|
|
|
|
DWORD VFormatToFourCC(VideoFormat format)
|
|
{
|
|
switch (format) {
|
|
/* raw formats */
|
|
case VideoFormat::ARGB:
|
|
return MAKEFOURCC('A', 'R', 'G', 'B');
|
|
case VideoFormat::XRGB:
|
|
return MAKEFOURCC('R', 'G', 'B', '4');
|
|
|
|
/* planar YUV formats */
|
|
case VideoFormat::I420:
|
|
return MAKEFOURCC('I', '4', '2', '0');
|
|
case VideoFormat::NV12:
|
|
return MAKEFOURCC('N', 'V', '1', '2');
|
|
case VideoFormat::YV12:
|
|
return MAKEFOURCC('Y', 'V', '1', '2');
|
|
case VideoFormat::Y800:
|
|
return MAKEFOURCC('Y', '8', '0', '0');
|
|
case VideoFormat::P010:
|
|
return MAKEFOURCC('P', '0', '1', '0');
|
|
|
|
/* packed YUV formats */
|
|
case VideoFormat::YVYU:
|
|
return MAKEFOURCC('Y', 'V', 'Y', 'U');
|
|
case VideoFormat::YUY2:
|
|
return MAKEFOURCC('Y', 'U', 'Y', '2');
|
|
case VideoFormat::UYVY:
|
|
return MAKEFOURCC('U', 'Y', 'V', 'Y');
|
|
case VideoFormat::HDYC:
|
|
return MAKEFOURCC('H', 'D', 'Y', 'C');
|
|
|
|
/* encoded formats */
|
|
case VideoFormat::MJPEG:
|
|
return MAKEFOURCC('M', 'J', 'P', 'G');
|
|
case VideoFormat::H264:
|
|
return MAKEFOURCC('H', '2', '6', '4');
|
|
#ifdef ENABLE_HEVC
|
|
case VideoFormat::HEVC:
|
|
return MAKEFOURCC('H', 'E', 'V', 'C');
|
|
#endif
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
GUID VFormatToSubType(VideoFormat format)
|
|
{
|
|
switch (format) {
|
|
/* raw formats */
|
|
case VideoFormat::ARGB:
|
|
return MEDIASUBTYPE_ARGB32;
|
|
case VideoFormat::XRGB:
|
|
return MEDIASUBTYPE_RGB32;
|
|
|
|
/* planar YUV formats */
|
|
case VideoFormat::I420:
|
|
return MEDIASUBTYPE_I420;
|
|
case VideoFormat::NV12:
|
|
return MEDIASUBTYPE_NV12;
|
|
case VideoFormat::YV12:
|
|
return MEDIASUBTYPE_YV12;
|
|
case VideoFormat::Y800:
|
|
return MEDIASUBTYPE_Y800;
|
|
case VideoFormat::P010:
|
|
return MEDIASUBTYPE_P010;
|
|
|
|
/* packed YUV formats */
|
|
case VideoFormat::YVYU:
|
|
return MEDIASUBTYPE_YVYU;
|
|
case VideoFormat::YUY2:
|
|
return MEDIASUBTYPE_YUY2;
|
|
case VideoFormat::UYVY:
|
|
return MEDIASUBTYPE_UYVY;
|
|
|
|
/* encoded formats */
|
|
case VideoFormat::MJPEG:
|
|
return MEDIASUBTYPE_MJPG;
|
|
case VideoFormat::H264:
|
|
return MEDIASUBTYPE_H264;
|
|
#ifdef ENABLE_HEVC
|
|
case VideoFormat::HEVC:
|
|
return MEDIASUBTYPE_HEVC;
|
|
#endif
|
|
|
|
default:
|
|
return GUID();
|
|
}
|
|
}
|
|
|
|
WORD VFormatBits(VideoFormat format)
|
|
{
|
|
switch (format) {
|
|
/* raw formats */
|
|
case VideoFormat::ARGB:
|
|
case VideoFormat::XRGB:
|
|
return 32;
|
|
|
|
/* planar YUV formats */
|
|
case VideoFormat::I420:
|
|
case VideoFormat::NV12:
|
|
case VideoFormat::YV12:
|
|
return 12;
|
|
case VideoFormat::Y800:
|
|
return 8;
|
|
|
|
/* packed YUV formats */
|
|
case VideoFormat::YVYU:
|
|
case VideoFormat::YUY2:
|
|
case VideoFormat::UYVY:
|
|
return 16;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
WORD VFormatPlanes(VideoFormat format)
|
|
{
|
|
switch (format) {
|
|
/* raw formats */
|
|
case VideoFormat::ARGB:
|
|
case VideoFormat::XRGB:
|
|
return 1;
|
|
|
|
/* planar YUV formats */
|
|
case VideoFormat::I420:
|
|
return 3;
|
|
case VideoFormat::NV12:
|
|
case VideoFormat::YV12:
|
|
return 2;
|
|
case VideoFormat::Y800:
|
|
return 1;
|
|
|
|
/* packed YUV formats */
|
|
case VideoFormat::YVYU:
|
|
case VideoFormat::YUY2:
|
|
case VideoFormat::UYVY:
|
|
return 1;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static bool GetFourCCVFormat(DWORD fourCC, VideoFormat &format)
|
|
{
|
|
switch (fourCC) {
|
|
/* raw formats */
|
|
case MAKEFOURCC('R', 'G', 'B', '2'):
|
|
format = VideoFormat::XRGB;
|
|
break;
|
|
case MAKEFOURCC('R', 'G', 'B', '4'):
|
|
format = VideoFormat::XRGB;
|
|
break;
|
|
case MAKEFOURCC('A', 'R', 'G', 'B'):
|
|
format = VideoFormat::ARGB;
|
|
break;
|
|
|
|
/* planar YUV formats */
|
|
case MAKEFOURCC('I', '4', '2', '0'):
|
|
case MAKEFOURCC('I', 'Y', 'U', 'V'):
|
|
format = VideoFormat::I420;
|
|
break;
|
|
case MAKEFOURCC('Y', 'V', '1', '2'):
|
|
format = VideoFormat::YV12;
|
|
break;
|
|
case MAKEFOURCC('N', 'V', '1', '2'):
|
|
format = VideoFormat::NV12;
|
|
break;
|
|
case MAKEFOURCC('Y', '8', '0', '0'):
|
|
format = VideoFormat::Y800;
|
|
break;
|
|
case MAKEFOURCC('P', '0', '1', '0'):
|
|
format = VideoFormat::P010;
|
|
break;
|
|
|
|
/* packed YUV formats */
|
|
case MAKEFOURCC('Y', 'V', 'Y', 'U'):
|
|
format = VideoFormat::YVYU;
|
|
break;
|
|
case MAKEFOURCC('Y', 'U', 'Y', '2'):
|
|
format = VideoFormat::YUY2;
|
|
break;
|
|
case MAKEFOURCC('U', 'Y', 'V', 'Y'):
|
|
format = VideoFormat::UYVY;
|
|
break;
|
|
case MAKEFOURCC('H', 'D', 'Y', 'C'):
|
|
format = VideoFormat::HDYC;
|
|
break;
|
|
|
|
/* compressed formats */
|
|
case MAKEFOURCC('H', '2', '6', '4'):
|
|
format = VideoFormat::H264;
|
|
break;
|
|
#ifdef ENABLE_HEVC
|
|
case MAKEFOURCC('H', 'E', 'V', 'C'):
|
|
format = VideoFormat::HEVC;
|
|
break;
|
|
#endif
|
|
|
|
/* compressed formats that can automatically create intermediary
|
|
* filters for decompression */
|
|
case MAKEFOURCC('M', 'J', 'P', 'G'):
|
|
format = VideoFormat::MJPEG;
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GetMediaTypeVFormat(const AM_MEDIA_TYPE &mt, VideoFormat &format)
|
|
{
|
|
if (mt.majortype != MEDIATYPE_Video)
|
|
return false;
|
|
|
|
const BITMAPINFOHEADER *bmih = GetBitmapInfoHeader(mt);
|
|
|
|
format = VideoFormat::Unknown;
|
|
|
|
/* raw formats */
|
|
if (mt.subtype == MEDIASUBTYPE_RGB24)
|
|
format = VideoFormat::XRGB;
|
|
else if (mt.subtype == MEDIASUBTYPE_RGB32)
|
|
format = VideoFormat::XRGB;
|
|
else if (mt.subtype == MEDIASUBTYPE_ARGB32)
|
|
format = VideoFormat::ARGB;
|
|
|
|
/* planar YUV formats */
|
|
else if (mt.subtype == MEDIASUBTYPE_I420)
|
|
format = VideoFormat::I420;
|
|
else if (mt.subtype == MEDIASUBTYPE_IYUV)
|
|
format = VideoFormat::I420;
|
|
else if (mt.subtype == MEDIASUBTYPE_YV12)
|
|
format = VideoFormat::YV12;
|
|
else if (mt.subtype == MEDIASUBTYPE_NV12)
|
|
format = VideoFormat::NV12;
|
|
else if (mt.subtype == MEDIASUBTYPE_Y800)
|
|
format = VideoFormat::Y800;
|
|
else if (mt.subtype == MEDIASUBTYPE_P010)
|
|
format = VideoFormat::P010;
|
|
|
|
/* packed YUV formats */
|
|
else if (mt.subtype == MEDIASUBTYPE_YVYU)
|
|
format = VideoFormat::YVYU;
|
|
else if (mt.subtype == MEDIASUBTYPE_YUY2)
|
|
format = VideoFormat::YUY2;
|
|
else if (mt.subtype == MEDIASUBTYPE_UYVY)
|
|
format = VideoFormat::UYVY;
|
|
|
|
/* compressed formats */
|
|
else if (mt.subtype == MEDIASUBTYPE_H264)
|
|
format = VideoFormat::H264;
|
|
#ifdef ENABLE_HEVC
|
|
else if (mt.subtype == MEDIASUBTYPE_HEVC)
|
|
format = VideoFormat::HEVC;
|
|
#endif
|
|
|
|
/* compressed formats that can automatically create intermediary
|
|
* filters for decompression */
|
|
else if (mt.subtype == MEDIASUBTYPE_MJPG)
|
|
format = VideoFormat::MJPEG;
|
|
|
|
/* no valid types, check fourcc value instead */
|
|
else
|
|
return bmih ? GetFourCCVFormat(bmih->biCompression, format)
|
|
: false;
|
|
|
|
return true;
|
|
}
|
|
|
|
}; /* namespace DShow */
|