obs_core_video_mix
+ -

obs_core_video_mix创建

2024-07-01 9 0

obs_core_video_mix创建使用函数obs_create_video_mix创建,不过对外使用的其实是obs_view_add2和obs_view_add。

在OBS中,创建obs_core_video_mix有两处,分别为:

static int obs_init_video(struct obs_video_info *ovi)
{
...
    //main_view增加至MIX,并设置为main
    if (!obs_view_add2(&obs->data.main_view, ovi))
        return OBS_VIDEO_FAIL;
...
}

bool BasicOutputHandler::StartVirtualCam()
{
...
    if (!virtualCamVideo)
    {
        virtualCamVideo = typeIsProgram ? obs_get_video(): obs_view_add(virtualCamView);

        if (!virtualCamVideo)
            return false;
    }
...
}

而obs_view_add与obs_view_add2的关系如下:

video_t *obs_view_add(obs_view_t *view)
{
    if (!obs->video.main_mix)
        return NULL;
    return obs_view_add2(view, &obs->video.main_mix->ovi);
}

而其入口的参数view的成员就是obs_view。

struct obs_view {
    pthread_mutex_t channels_mutex;
    obs_source_t *channels[MAX_CHANNELS];
};

obs_view_add2

obs_view_add2函数如下:

video_t *obs_view_add2(obs_view_t *view, struct obs_video_info *ovi)
{
    if (!view || !ovi)
        return NULL;

    struct obs_core_video_mix *mix = obs_create_video_mix(ovi);
    if (!mix) {
        return NULL;
    }
    mix->view = view;

    pthread_mutex_lock(&obs->video.mixes_mutex);
    da_push_back(obs->video.mixes, &mix);
    set_main_mix();
    pthread_mutex_unlock(&obs->video.mixes_mutex);

    return mix->video;
}

其首先通过obs_create_video_mix创建该结构体内存,当然在其内部需要进行必要的初始化。
然后赋值view成员。
最后将创建的obs_core_video_mix对象存储在obs->video.mixes数组中。

obs_create_video_mix

obs_create_video_mix函数为:

struct obs_core_video_mix *obs_create_video_mix(struct obs_video_info *ovi)
{
    //申请结构体内存空间
    struct obs_core_video_mix *video =    bzalloc(sizeof(struct obs_core_video_mix));

    //初始化
    if (obs_init_video_mix(ovi, video) != OBS_VIDEO_SUCCESS)
    {
        bfree(video);
        video = NULL;
    }
    return video;
}

obs_init_video_mix

obs_init_video_mix源码如下:

static int obs_init_video_mix(struct obs_video_info *ovi, struct obs_core_video_mix *video)
{
    struct video_output_info vi;

    pthread_mutex_init_value(&video->gpu_encoder_mutex);

    make_video_info(&vi, ovi);
    video->ovi = *ovi;

    /* main view graphics thread drives all frame output,
     * so share FPS settings for aux views */
    pthread_mutex_lock(&obs->video.mixes_mutex);
    size_t num = obs->video.mixes.num;
    if (num && obs->video.main_mix)
    {
        struct obs_video_info main_ovi = obs->video.main_mix->ovi;
        video->ovi.fps_num = main_ovi.fps_num;
        video->ovi.fps_den = main_ovi.fps_den;
    }
    pthread_mutex_unlock(&obs->video.mixes_mutex);

    video->gpu_conversion = ovi->gpu_conversion;
    video->gpu_was_active = false;
    video->raw_was_active = false;
    video->was_active = false;

    set_video_matrix(video, &vi);

    int errorcode = video_output_open(&video->video, &vi);
    if (errorcode != VIDEO_OUTPUT_SUCCESS) 
    {
        if (errorcode == VIDEO_OUTPUT_INVALIDPARAM) {
            blog(LOG_ERROR, "Invalid video parameters specified");
            return OBS_VIDEO_INVALID_PARAM;
        } else {
            blog(LOG_ERROR, "Could not open video output");
        }
        return OBS_VIDEO_FAIL;
    }

    if (pthread_mutex_init(&video->gpu_encoder_mutex, NULL) < 0)
        return OBS_VIDEO_FAIL;

    gs_enter_context(obs->video.graphics);

    if (video->gpu_conversion && !obs_init_gpu_conversion(video))
        return OBS_VIDEO_FAIL;
    if (!obs_init_textures(video))
        return OBS_VIDEO_FAIL;

    gs_leave_context();

    return OBS_VIDEO_SUCCESS;
}

这里比较重要的的是obs_init_textures函数。

obs_init_textures

  • 对于NV12或P010格式,提供了编码格式函数。
  • 如果支持CPU转换,提供其surfaces
  • 获取颜色空间,创建render_texture和output_texture纹理。

    static bool obs_init_textures(struct obs_core_video_mix *video)
    {
      const struct video_output_info *info =    video_output_get_info(video->video);
    
      bool success = true;
    
      enum gs_color_format format = GS_BGRA;
      switch (info->format) {
      case VIDEO_FORMAT_I010:
      case VIDEO_FORMAT_P010:
      case VIDEO_FORMAT_I210:
      case VIDEO_FORMAT_I412:
      case VIDEO_FORMAT_YA2L:
      case VIDEO_FORMAT_P216:
      case VIDEO_FORMAT_P416:
          format = GS_RGBA16F;
          break;
      default:
          break;
      }
    
      for (size_t i = 0; i < NUM_TEXTURES/*2*/; i++)
      {
    #ifdef _WIN32
          if (video->using_nv12_tex)
          {
              video->copy_surfaces_encode[i] =gs_stagesurface_create_nv12(info->width,  info->height);
              if (!video->copy_surfaces_encode[i]) 
              {
                  success = false;
                  break;
              }
          }
          else if (video->using_p010_tex)
          {
              video->copy_surfaces_encode[i] =gs_stagesurface_create_p010(info->width, info->height);
              if (!video->copy_surfaces_encode[i])
              {
                  success = false;
                  break;
              }
          }
    #endif
    
          if (video->gpu_conversion)
          {
              if (!obs_init_gpu_copy_surfaces(video, i)) 
              {
                  success = false;
                  break;
              }
          } 
          else
          {
              video->copy_surfaces[i][0] = gs_stagesurface_create(info->width, info->height, format);
              if (!video->copy_surfaces[i][0])
              {
                  success = false;
                  break;
              }
          }
      }
    
      enum gs_color_space space = GS_CS_SRGB;
      switch (info->colorspace) {
      case VIDEO_CS_2100_PQ:
      case VIDEO_CS_2100_HLG:
          space = GS_CS_709_EXTENDED;
          break;
      default:
          switch (info->format) {
          case VIDEO_FORMAT_I010:
          case VIDEO_FORMAT_P010:
          case VIDEO_FORMAT_P216:
          case VIDEO_FORMAT_P416:
              space = GS_CS_SRGB_16F;
              break;
          default:
              space = GS_CS_SRGB;
              break;
          }
          break;
      }
    
      //源渲染纹理
      video->render_texture =    gs_texture_create(video->ovi.base_width, video->ovi.base_height,  format, 1, NULL, GS_RENDER_TARGET);
      if (!video->render_texture)
          success = false;
    
      //转换后的纹理
      video->output_texture = gs_texture_create(info->width, info->height, format, 1, NULL, GS_RENDER_TARGET);
      if (!video->output_texture)
          success = false;
    
      if (success)
      {
          video->render_space = space;
      }
      else
      {
          //创建texture失败,销毁
      }
      return success;
    }
    

0 篇笔记 写笔记

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

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

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