OBS图形及渲染
+ -

obs视频参数配置

2024-04-26 47 0

由于本人对高级图形编程从未接触过,故为学习OBS也需要浅浅的了解一下。
OBS关于图形配置及相关的回调函数调用,由一个结构体obs_video_info主载。

struct obs_video_info {
#ifndef SWIG
    /**
     * Graphics module to use (usually "libobs-opengl" or "libobs-d3d11")
     */
    const char *graphics_module;
#endif

    uint32_t fps_num; /**< Output FPS numerator */
    uint32_t fps_den; /**< Output FPS denominator */

    uint32_t base_width;  /**< Base compositing width */
    uint32_t base_height; /**< Base compositing height */

    uint32_t output_width;           /**< Output width */
    uint32_t output_height;          /**< Output height */
    enum video_format output_format; /**< Output format */

    /** Video adapter index to use (NOTE: avoid for optimus laptops) */
    uint32_t adapter;

    /** Use shaders to convert to different color formats */
    bool gpu_conversion;

    enum video_colorspace colorspace; /**< YUV type (if YUV) */
    enum video_range_type range;      /**< YUV range (if YUV) */

    enum obs_scale_type scale_type; /**< How to scale if scaling */
};

关于这些参数的设由在ResetVideo中设置,其参数来源于配置文件和默认参数。

int OBSBasic::ResetVideo()
{
    if (outputHandler && outputHandler->Active())
        return OBS_VIDEO_CURRENTLY_ACTIVE;

    ProfileScope("OBSBasic::ResetVideo");

    struct obs_video_info ovi;
    int ret;

    GetConfigFPS(ovi.fps_num, ovi.fps_den);

    const char *colorFormat =config_get_string(basicConfig, "Video", "ColorFormat");
    const char *colorSpace = config_get_string(basicConfig, "Video", "ColorSpace");
    const char *colorRange =config_get_string(basicConfig, "Video", "ColorRange");

    ovi.graphics_module = App()->GetRenderModule();
    ovi.base_width =(uint32_t)config_get_uint(basicConfig, "Video", "BaseCX");
    ovi.base_height =(uint32_t)config_get_uint(basicConfig, "Video", "BaseCY");
    ovi.output_width =(uint32_t)config_get_uint(basicConfig, "Video", "OutputCX");
    ovi.output_height =(uint32_t)config_get_uint(basicConfig, "Video", "OutputCY");
    ovi.output_format = GetVideoFormatFromName(colorFormat);
    ovi.colorspace = GetVideoColorSpaceFromName(colorSpace);
    ovi.range = astrcmpi(colorRange, "Full") == 0 ? VIDEO_RANGE_FULL: VIDEO_RANGE_PARTIAL;
    ovi.adapter =config_get_uint(App()->GlobalConfig(), "Video", "AdapterIdx");
    ovi.gpu_conversion = true;
    ovi.scale_type = GetScaleType(basicConfig);

    if (ovi.base_width < 32 || ovi.base_height < 32) {
        ovi.base_width = 1920;
        ovi.base_height = 1080;
        config_set_uint(basicConfig, "Video", "BaseCX", 1920);
        config_set_uint(basicConfig, "Video", "BaseCY", 1080);
    }

    if (ovi.output_width < 32 || ovi.output_height < 32) 
    {
        ovi.output_width = ovi.base_width;
        ovi.output_height = ovi.base_height;
        config_set_uint(basicConfig, "Video", "OutputCX",ovi.base_width);
        config_set_uint(basicConfig, "Video", "OutputCY",ovi.base_height);
    }

    ret = AttemptToResetVideo(&ovi);
    if (ret == OBS_VIDEO_CURRENTLY_ACTIVE) {
        blog(LOG_WARNING, "Tried to reset when already active");
        return ret;
    }

    if (ret == OBS_VIDEO_SUCCESS) {
        ResizePreview(ovi.base_width, ovi.base_height);
        if (program)
            ResizeProgram(ovi.base_width, ovi.base_height);

        float sdr_white_level = (float)config_get_uint(basicConfig, "Video", "SdrWhiteLevel");
        float hdr_nominal_peak_level = (float)config_get_uint(basicConfig, "Video","HdrNominalPeakLevel");
        obs_set_video_levels(sdr_white_level, hdr_nominal_peak_level);
        OBSBasicStats::InitializeValues();
        OBSProjector::UpdateMultiviewProjectors();
    }

    return ret;
}

所以最终调用AttemptToResetVideo->obs_reset_video来进行初始化:

其中根据标识:

  • graphics_module指定了是使用OPENGL还是D3D11,其值为DLL的名称字符串
  • fps_num:帧率的分子
  • fps_den:帧率的分母,
    故实际的帧率为:
double obsFPS = (double)ovi.fps_num / (double)ovi.fps_den;

另外:

static int obs_init_video(struct obs_video_info *ovi)
{
    struct obs_core_video *video = &obs->video;
//一帧多少ns den/num 表示1帧多长时间
    //
    // ovi.fps_num = 30 000;
    // ovi.fps_den = 1001; 1001秒30 000 帧

    video->video_frame_interval_ns = util_mul_div64(1000000000ULL, ovi->fps_den, ovi->fps_num);  //den*1000000000ULL/num
    video->video_half_frame_interval_ns = util_mul_div64(500000000ULL, ovi->fps_den, ovi->fps_num);
...
}

实际为 rtn = num*mul/div
static inline uint64_t util_mul_div64(uint64_t num, uint64_t mul, uint64_t div)
{
#if defined(_MSC_VER) && defined(_M_X64) && (_MSC_VER >= 1920)
    unsigned __int64 high;
    const unsigned __int64 low = _umul128(num, mul, &high);
    unsigned __int64 rem;
    return _udiv128(high, low, div, &rem);
#else
    const uint64_t rem = num % div;
    return (num / div) * mul + (rem * mul) / div;
#endif
}
  • base_width:画面宽度
  • base_height:画布高度
  • output_width:输出宽度(和画布不同需要缩放)
  • output_height:同output_width
    输出的长和宽需要进行字节对齐:
      /* align to multiple-of-two and SSE alignment sizes */
      ovi->output_width &= 0xFFFFFFFC;//宽度必须是4的倍数
      ovi->output_height &= 0xFFFFFFFE;//长度必须是2的倍数
    
  • video_format:视频格式
  • adapter:适配器索引
  • gpu_conversion:GPUC加速
  • video_colorspace:颜色空间(标准/扩展)
  • video_range_type:颜色范围
  • obs_scale_type:缩放方式

这些参数对应于OBS的一些配置:
画布及输出
图像格式

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!