From 575ad9bcb28e49cef0ab855fc9517d78316105f1 Mon Sep 17 00:00:00 2001 From: ferrreo Date: Fri, 28 Apr 2023 19:46:57 +0100 Subject: [PATCH] Add missing patches --- patches/add-plugins.patch | 14 + patches/remove-ffmpeg-vaapi.patch | 1149 +++++++++++++++++++++++++++++ 2 files changed, 1163 insertions(+) create mode 100644 patches/add-plugins.patch create mode 100644 patches/remove-ffmpeg-vaapi.patch diff --git a/patches/add-plugins.patch b/patches/add-plugins.patch new file mode 100644 index 0000000..63a1ba7 --- /dev/null +++ b/patches/add-plugins.patch @@ -0,0 +1,14 @@ +diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt +index d20bce142..febeff6b7 100644 +--- a/plugins/CMakeLists.txt ++++ b/plugins/CMakeLists.txt +@@ -60,6 +60,9 @@ elseif(OS_LINUX) + add_subdirectory(vlc-video) + add_subdirectory(sndio) + add_subdirectory(obs-vst) ++ add_subdirectory(obs-vkcapture) ++ add_subdirectory(obs-source-record) ++ + + check_obs_browser() + elseif(OS_FREEBSD) diff --git a/patches/remove-ffmpeg-vaapi.patch b/patches/remove-ffmpeg-vaapi.patch new file mode 100644 index 0000000..e871297 --- /dev/null +++ b/patches/remove-ffmpeg-vaapi.patch @@ -0,0 +1,1149 @@ +From f8f2e1fd41b6f8cde6940db3f9c65ca4a329d499 Mon Sep 17 00:00:00 2001 +From: GloriousEggroll +Date: Sat, 1 Apr 2023 16:57:18 -0600 +Subject: [PATCH] remove ffmpeg vaapi encoder (we replace it with obs-vaapi + plugin which uses gstreamer) + +--- + plugins/obs-ffmpeg/CMakeLists.txt | 2 +- + plugins/obs-ffmpeg/cmake/legacy.cmake | 2 +- + plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c | 1009 ------------------------- + plugins/obs-ffmpeg/obs-ffmpeg.c | 59 -- + 4 files changed, 2 insertions(+), 1070 deletions(-) + delete mode 100644 plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c + +diff --git a/plugins/obs-ffmpeg/CMakeLists.txt b/plugins/obs-ffmpeg/CMakeLists.txt +index 2d07960..0632896 100644 +--- a/plugins/obs-ffmpeg/CMakeLists.txt ++++ b/plugins/obs-ffmpeg/CMakeLists.txt +@@ -114,7 +114,7 @@ elseif(OS_LINUX OR OS_FREEBSD) + find_package(Libpci REQUIRED) + find_package(Vulkan REQUIRED) + +- target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c vaapi-utils.h texture-amf.cpp) ++ target_sources(obs-ffmpeg PRIVATE vaapi-utils.c vaapi-utils.h texture-amf.cpp) + target_link_libraries(obs-ffmpeg PRIVATE Libva::va Libva::drm Libpci::pci Vulkan::Vulkan) + endif() + +diff --git a/plugins/obs-ffmpeg/cmake/legacy.cmake b/plugins/obs-ffmpeg/cmake/legacy.cmake +index b29eef6..4b92825 100644 +--- a/plugins/obs-ffmpeg/cmake/legacy.cmake ++++ b/plugins/obs-ffmpeg/cmake/legacy.cmake +@@ -110,7 +110,7 @@ elseif(OS_POSIX AND NOT OS_MACOS) + find_package(Libva REQUIRED) + find_package(Libpci REQUIRED) + find_package(Vulkan REQUIRED) +- target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c vaapi-utils.h texture-amf.cpp) ++ target_sources(obs-ffmpeg PRIVATE vaapi-utils.c vaapi-utils.h texture-amf.cpp) + target_link_libraries(obs-ffmpeg PRIVATE Libva::va Libva::drm LIBPCI::LIBPCI Vulkan::Vulkan) + endif() + +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +deleted file mode 100644 +index 79c7f3f..0000000 +--- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c ++++ /dev/null +@@ -1,1009 +0,0 @@ +-/****************************************************************************** +- Copyright (C) 2016 by Hugh Bailey +- +- This program is free software: you can redistribute it and/or modify +- it under the terms of the GNU General Public License as published by +- the Free Software Foundation, either version 2 of the License, or +- (at your option) any later version. +- +- This program 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 General Public License for more details. +- +- You should have received a copy of the GNU General Public License +- along with this program. If not, see . +-******************************************************************************/ +- +-#include +- +-#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 27, 100) +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#ifdef ENABLE_HEVC +-#include +-#endif +- +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include "vaapi-utils.h" +-#include "obs-ffmpeg-formats.h" +- +-#define do_log(level, format, ...) \ +- blog(level, "[FFmpeg VAAPI encoder: '%s'] " format, \ +- obs_encoder_get_name(enc->encoder), ##__VA_ARGS__) +- +-#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__) +-#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) +-#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__) +- +-struct vaapi_encoder { +- obs_encoder_t *encoder; +- +- AVBufferRef *vadevice_ref; +- AVBufferRef *vaframes_ref; +- +- const AVCodec *vaapi; +- AVCodecContext *context; +- +- AVPacket *packet; +- +- AVFrame *vframe; +- +- DARRAY(uint8_t) buffer; +- +- uint8_t *header; +- size_t header_size; +- +- uint8_t *sei; +- size_t sei_size; +- +- int height; +- bool first_packet; +- bool initialized; +-}; +- +-static const char *h264_vaapi_getname(void *unused) +-{ +- UNUSED_PARAMETER(unused); +- return "FFmpeg VAAPI H.264"; +-} +- +-#ifdef ENABLE_HEVC +-static const char *hevc_vaapi_getname(void *unused) +-{ +- UNUSED_PARAMETER(unused); +- return "FFmpeg VAAPI HEVC"; +-} +-#endif +- +-static inline bool h264_valid_format(enum video_format format) +-{ +- return format == VIDEO_FORMAT_NV12; +-} +- +-#ifdef ENABLE_HEVC +-static inline bool hevc_valid_format(enum video_format format) +-{ +- return (format == VIDEO_FORMAT_NV12) || (format == VIDEO_FORMAT_P010); +-} +-#endif +- +-static void h264_vaapi_video_info(void *data, struct video_scale_info *info) +-{ +- struct vaapi_encoder *enc = data; +- enum video_format pref_format; +- +- pref_format = obs_encoder_get_preferred_video_format(enc->encoder); +- +- if (!h264_valid_format(pref_format)) { +- pref_format = h264_valid_format(info->format) +- ? info->format +- : VIDEO_FORMAT_NV12; +- } +- +- info->format = pref_format; +-} +- +-#ifdef ENABLE_HEVC +-static void hevc_vaapi_video_info(void *data, struct video_scale_info *info) +-{ +- struct vaapi_encoder *enc = data; +- enum video_format pref_format; +- +- pref_format = obs_encoder_get_preferred_video_format(enc->encoder); +- +- if (!hevc_valid_format(pref_format)) { +- pref_format = hevc_valid_format(info->format) +- ? info->format +- : VIDEO_FORMAT_NV12; +- } +- +- info->format = pref_format; +-} +-#endif +- +-static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path) +-{ +- int ret; +- +- ret = av_hwdevice_ctx_create(&enc->vadevice_ref, AV_HWDEVICE_TYPE_VAAPI, +- path, NULL, 0); +- if (ret < 0) { +- warn("Failed to create VAAPI device context: %s", +- av_err2str(ret)); +- return false; +- } +- +- enc->vaframes_ref = av_hwframe_ctx_alloc(enc->vadevice_ref); +- if (!enc->vaframes_ref) { +- warn("Failed to alloc HW frames context"); +- return false; +- } +- +- AVHWFramesContext *frames_ctx = +- (AVHWFramesContext *)enc->vaframes_ref->data; +- frames_ctx->format = AV_PIX_FMT_VAAPI; +- frames_ctx->sw_format = enc->context->pix_fmt; +- frames_ctx->width = enc->context->width; +- frames_ctx->height = enc->context->height; +- frames_ctx->initial_pool_size = 20; +- +- ret = av_hwframe_ctx_init(enc->vaframes_ref); +- if (ret < 0) { +- warn("Failed to init HW frames context: %s", av_err2str(ret)); +- return false; +- } +- +- /* 2. Create software frame and picture */ +- enc->vframe = av_frame_alloc(); +- if (!enc->vframe) { +- warn("Failed to allocate video frame"); +- return false; +- } +- +- enc->vframe->format = enc->context->pix_fmt; +- enc->vframe->width = enc->context->width; +- enc->vframe->height = enc->context->height; +- enc->vframe->colorspace = enc->context->colorspace; +- enc->vframe->color_range = enc->context->color_range; +- enc->vframe->chroma_location = enc->context->chroma_sample_location; +- +- ret = av_frame_get_buffer(enc->vframe, base_get_alignment()); +- if (ret < 0) { +- warn("Failed to allocate vframe: %s", av_err2str(ret)); +- return false; +- } +- +- /* 3. set up codec */ +- enc->context->pix_fmt = AV_PIX_FMT_VAAPI; +- enc->context->hw_frames_ctx = av_buffer_ref(enc->vaframes_ref); +- +- ret = avcodec_open2(enc->context, enc->vaapi, NULL); +- if (ret < 0) { +- warn("Failed to open VAAPI codec: %s", av_err2str(ret)); +- return false; +- } +- +- enc->packet = av_packet_alloc(); +- +- enc->initialized = true; +- return true; +-} +- +-/* "Allowed" options per Rate Control +- * See FFMPEG libavcodec/vaapi_encode.c (vaapi_encode_rc_modes) +- */ +-typedef struct { +- const char *name; +- bool qp; +- bool bitrate; +- bool maxrate; +-} rc_mode_t; +- +-static const rc_mode_t *get_rc_mode(const char *name) +-{ +- /* Set "allowed" options per Rate Control */ +- static const rc_mode_t RC_MODES[] = { +- {.name = "CBR", .qp = false, .bitrate = true, .maxrate = false}, +- {.name = "CQP", .qp = true, .bitrate = false, .maxrate = false}, +- {.name = "VBR", .qp = false, .bitrate = true, .maxrate = true}, +- {0}}; +- +- const rc_mode_t *rc_mode = RC_MODES; +- +- while (!!rc_mode->name && strcmp(rc_mode->name, name) != 0) +- rc_mode++; +- +- return rc_mode ? rc_mode : RC_MODES; +-} +- +-static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) +-{ +- struct vaapi_encoder *enc = data; +- +- const char *device = obs_data_get_string(settings, "vaapi_device"); +- +- const char *rate_control = +- obs_data_get_string(settings, "rate_control"); +- const rc_mode_t *rc_mode = get_rc_mode(rate_control); +- bool cbr = strcmp(rc_mode->name, "CBR") == 0; +- +- int profile = (int)obs_data_get_int(settings, "profile"); +- int bf = (int)obs_data_get_int(settings, "bf"); +- int qp = rc_mode->qp ? (int)obs_data_get_int(settings, "qp") : 0; +- +- av_opt_set_int(enc->context->priv_data, "qp", qp, 0); +- +- int level = (int)obs_data_get_int(settings, "level"); +- int bitrate = rc_mode->bitrate +- ? (int)obs_data_get_int(settings, "bitrate") +- : 0; +- int maxrate = rc_mode->maxrate +- ? (int)obs_data_get_int(settings, "maxrate") +- : 0; +- int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); +- +- /* For Rate Control which allows maxrate, FFMPEG will give +- * an error if maxrate > bitrate. To prevent that set maxrate +- * to 0. +- * For CBR, maxrate = bitrate +- */ +- if (cbr) +- maxrate = bitrate; +- else if (rc_mode->maxrate && maxrate && maxrate < bitrate) +- maxrate = 0; +- +- video_t *video = obs_encoder_video(enc->encoder); +- const struct video_output_info *voi = video_output_get_info(video); +- struct video_scale_info info; +- +- info.format = voi->format; +- info.colorspace = voi->colorspace; +- info.range = voi->range; +- +-#ifdef ENABLE_HEVC +- if (hevc) { +- if ((profile == FF_PROFILE_HEVC_MAIN) && +- (info.format == VIDEO_FORMAT_P010)) { +- warn("Forcing Main10 for P010"); +- profile = FF_PROFILE_HEVC_MAIN_10; +- } +- +- hevc_vaapi_video_info(enc, &info); +- } else +-#endif +- { +- h264_vaapi_video_info(enc, &info); +- } +- +- enc->context->profile = profile; +- enc->context->max_b_frames = bf; +- enc->context->level = level; +- enc->context->bit_rate = bitrate * 1000; +- enc->context->rc_max_rate = maxrate * 1000; +- +- enc->context->width = obs_encoder_get_width(enc->encoder); +- enc->context->height = obs_encoder_get_height(enc->encoder); +- +- enc->context->time_base = (AVRational){voi->fps_den, voi->fps_num}; +- const enum AVPixelFormat pix_fmt = +- obs_to_ffmpeg_video_format(info.format); +- enc->context->pix_fmt = pix_fmt; +- enc->context->color_range = info.range == VIDEO_RANGE_FULL +- ? AVCOL_RANGE_JPEG +- : AVCOL_RANGE_MPEG; +- +- enum AVColorSpace colorspace = AVCOL_SPC_UNSPECIFIED; +- switch (info.colorspace) { +- case VIDEO_CS_601: +- enc->context->color_primaries = AVCOL_PRI_SMPTE170M; +- enc->context->color_trc = AVCOL_TRC_SMPTE170M; +- colorspace = AVCOL_SPC_SMPTE170M; +- break; +- case VIDEO_CS_DEFAULT: +- case VIDEO_CS_709: +- enc->context->color_primaries = AVCOL_PRI_BT709; +- enc->context->color_trc = AVCOL_TRC_BT709; +- colorspace = AVCOL_SPC_BT709; +- break; +- case VIDEO_CS_SRGB: +- enc->context->color_primaries = AVCOL_PRI_BT709; +- enc->context->color_trc = AVCOL_TRC_IEC61966_2_1; +- colorspace = AVCOL_SPC_BT709; +- break; +- case VIDEO_CS_2100_PQ: +- enc->context->color_primaries = AVCOL_PRI_BT2020; +- enc->context->color_trc = AVCOL_TRC_SMPTE2084; +- colorspace = AVCOL_SPC_BT2020_NCL; +- break; +- case VIDEO_CS_2100_HLG: +- enc->context->color_primaries = AVCOL_PRI_BT2020; +- enc->context->color_trc = AVCOL_TRC_ARIB_STD_B67; +- colorspace = AVCOL_SPC_BT2020_NCL; +- break; +- default: +- break; +- } +- +- enc->context->colorspace = colorspace; +- enc->context->chroma_sample_location = +- determine_chroma_location(pix_fmt, colorspace); +- +- if (keyint_sec > 0) { +- enc->context->gop_size = +- keyint_sec * voi->fps_num / voi->fps_den; +- } else { +- enc->context->gop_size = 120; +- } +- +- enc->height = enc->context->height; +- +- info("settings:\n" +- "\tdevice: %s\n" +- "\trate_control: %s\n" +- "\tprofile: %d\n" +- "\tlevel: %d\n" +- "\tqp: %d\n" +- "\tbitrate: %d\n" +- "\tmaxrate: %d\n" +- "\tkeyint: %d\n" +- "\twidth: %d\n" +- "\theight: %d\n" +- "\tb-frames: %d\n", +- device, rate_control, profile, level, qp, bitrate, maxrate, +- enc->context->gop_size, enc->context->width, enc->context->height, +- enc->context->max_b_frames); +- +- return vaapi_init_codec(enc, device); +-} +- +-static inline void flush_remaining_packets(struct vaapi_encoder *enc) +-{ +- int r_pkt = 1; +- +- while (r_pkt) { +-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101) +- if (avcodec_receive_packet(enc->context, enc->packet) < 0) +- break; +-#else +- if (avcodec_encode_video2(enc->context, enc->packet, NULL, +- &r_pkt) < 0) +- break; +-#endif +- +- if (r_pkt) +- av_packet_unref(enc->packet); +- } +-} +- +-static void vaapi_destroy(void *data) +-{ +- struct vaapi_encoder *enc = data; +- +- if (enc->initialized) +- flush_remaining_packets(enc); +- +- av_packet_free(&enc->packet); +- avcodec_free_context(&enc->context); +- av_frame_unref(enc->vframe); +- av_frame_free(&enc->vframe); +- av_buffer_unref(&enc->vaframes_ref); +- av_buffer_unref(&enc->vadevice_ref); +- da_free(enc->buffer); +- bfree(enc->header); +- bfree(enc->sei); +- +- bfree(enc); +-} +- +-static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, +- bool hevc) +-{ +- struct vaapi_encoder *enc; +-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100) +- avcodec_register_all(); +-#endif +- +- enc = bzalloc(sizeof(*enc)); +- enc->encoder = encoder; +- +- const char *const name = hevc ? "hevc_vaapi" : "h264_vaapi"; +- enc->vaapi = avcodec_find_encoder_by_name(name); +- +- enc->first_packet = true; +- +- blog(LOG_INFO, "---------------------------------"); +- +- if (!enc->vaapi) { +- warn("Couldn't find encoder"); +- goto fail; +- } +- +- enc->context = avcodec_alloc_context3(enc->vaapi); +- if (!enc->context) { +- warn("Failed to create codec context"); +- goto fail; +- } +- +- if (!vaapi_update(enc, settings, hevc)) +- goto fail; +- +- return enc; +- +-fail: +- vaapi_destroy(enc); +- return NULL; +-} +- +-static void *h264_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) +-{ +- return vaapi_create_internal(settings, encoder, false); +-} +- +-#ifdef ENABLE_HEVC +-static void *hevc_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) +-{ +- return vaapi_create_internal(settings, encoder, true); +-} +-#endif +- +-static inline void copy_data(AVFrame *pic, const struct encoder_frame *frame, +- int height, enum AVPixelFormat format) +-{ +- int h_chroma_shift, v_chroma_shift; +- av_pix_fmt_get_chroma_sub_sample(format, &h_chroma_shift, +- &v_chroma_shift); +- for (int plane = 0; plane < MAX_AV_PLANES; plane++) { +- if (!frame->data[plane]) +- continue; +- +- int frame_rowsize = (int)frame->linesize[plane]; +- int pic_rowsize = pic->linesize[plane]; +- int bytes = frame_rowsize < pic_rowsize ? frame_rowsize +- : pic_rowsize; +- int plane_height = height >> (plane ? v_chroma_shift : 0); +- +- for (int y = 0; y < plane_height; y++) { +- int pos_frame = y * frame_rowsize; +- int pos_pic = y * pic_rowsize; +- +- memcpy(pic->data[plane] + pos_pic, +- frame->data[plane] + pos_frame, bytes); +- } +- } +-} +- +-static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, +- struct encoder_packet *packet, +- bool *received_packet, bool hevc) +-{ +- struct vaapi_encoder *enc = data; +- AVFrame *hwframe = NULL; +- int got_packet; +- int ret; +- +- hwframe = av_frame_alloc(); +- if (!hwframe) { +- warn("vaapi_encode: failed to allocate hw frame"); +- return false; +- } +- +- ret = av_hwframe_get_buffer(enc->vaframes_ref, hwframe, 0); +- if (ret < 0) { +- warn("vaapi_encode: failed to get buffer for hw frame: %s", +- av_err2str(ret)); +- goto fail; +- } +- +- copy_data(enc->vframe, frame, enc->height, enc->context->pix_fmt); +- +- enc->vframe->pts = frame->pts; +- hwframe->pts = frame->pts; +- hwframe->width = enc->vframe->width; +- hwframe->height = enc->vframe->height; +- +- ret = av_hwframe_transfer_data(hwframe, enc->vframe, 0); +- if (ret < 0) { +- warn("vaapi_encode: failed to upload hw frame: %s", +- av_err2str(ret)); +- goto fail; +- } +- +- ret = av_frame_copy_props(hwframe, enc->vframe); +- if (ret < 0) { +- warn("vaapi_encode: failed to copy props to hw frame: %s", +- av_err2str(ret)); +- goto fail; +- } +- +-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101) +- ret = avcodec_send_frame(enc->context, hwframe); +- if (ret == 0) +- ret = avcodec_receive_packet(enc->context, enc->packet); +- +- got_packet = (ret == 0); +- +- if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) +- ret = 0; +-#else +- ret = avcodec_encode_video2(enc->context, enc->packet, hwframe, +- &got_packet); +-#endif +- if (ret < 0) { +- warn("vaapi_encode: Error encoding: %s", av_err2str(ret)); +- goto fail; +- } +- +- if (got_packet && enc->packet->size) { +- if (enc->first_packet) { +- uint8_t *new_packet; +- size_t size; +- +- enc->first_packet = false; +-#ifdef ENABLE_HEVC +- if (hevc) { +- obs_extract_hevc_headers( +- enc->packet->data, enc->packet->size, +- &new_packet, &size, &enc->header, +- &enc->header_size, &enc->sei, +- &enc->sei_size); +- } else +-#endif +- { +- obs_extract_avc_headers( +- enc->packet->data, enc->packet->size, +- &new_packet, &size, &enc->header, +- &enc->header_size, &enc->sei, +- &enc->sei_size); +- } +- +- da_copy_array(enc->buffer, new_packet, size); +- bfree(new_packet); +- } else { +- da_copy_array(enc->buffer, enc->packet->data, +- enc->packet->size); +- } +- +- packet->pts = enc->packet->pts; +- packet->dts = enc->packet->dts; +- packet->data = enc->buffer.array; +- packet->size = enc->buffer.num; +- packet->type = OBS_ENCODER_VIDEO; +-#ifdef ENABLE_HEVC +- if (hevc) { +- packet->keyframe = +- obs_hevc_keyframe(packet->data, packet->size); +- } else +-#endif +- { +- packet->keyframe = +- obs_avc_keyframe(packet->data, packet->size); +- } +- *received_packet = true; +- } else { +- *received_packet = false; +- } +- +- av_packet_unref(enc->packet); +- av_frame_free(&hwframe); +- return true; +- +-fail: +- av_frame_free(&hwframe); +- return false; +-} +- +-static bool h264_vaapi_encode(void *data, struct encoder_frame *frame, +- struct encoder_packet *packet, +- bool *received_packet) +-{ +- return vaapi_encode_internal(data, frame, packet, received_packet, +- false); +-} +- +-#ifdef ENABLE_HEVC +-static bool hevc_vaapi_encode(void *data, struct encoder_frame *frame, +- struct encoder_packet *packet, +- bool *received_packet) +-{ +- return vaapi_encode_internal(data, frame, packet, received_packet, +- true); +-} +-#endif +- +-static void set_visible(obs_properties_t *ppts, const char *name, bool visible) +-{ +- obs_property_t *p = obs_properties_get(ppts, name); +- obs_property_set_visible(p, visible); +-} +- +-static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) +-{ +-#ifdef ENABLE_HEVC +- const char *device = hevc ? vaapi_get_hevc_default_device() +- : vaapi_get_h264_default_device(); +-#else +- const char *const device = vaapi_get_h264_default_device(); +-#endif +- +- obs_data_set_default_string(settings, "vaapi_device", device); +-#ifdef ENABLE_HEVC +- if (hevc) { +- obs_data_set_default_int(settings, "profile", +- FF_PROFILE_HEVC_MAIN); +- +- } else +-#endif +- { +- obs_data_set_default_int(settings, "profile", +- FF_PROFILE_H264_CONSTRAINED_BASELINE); +- } +- obs_data_set_default_int(settings, "level", 40); +- obs_data_set_default_int(settings, "bitrate", 2500); +- obs_data_set_default_int(settings, "keyint_sec", 0); +- obs_data_set_default_int(settings, "bf", 0); +- obs_data_set_default_int(settings, "rendermode", 0); +- obs_data_set_default_int(settings, "qp", 20); +- obs_data_set_default_int(settings, "maxrate", 0); +- +- int drm_fd = -1; +- VADisplay va_dpy = vaapi_open_device(&drm_fd, device, "vaapi_defaults"); +- if (!va_dpy) +- return; +- +-#ifdef ENABLE_HEVC +- const VAProfile profile = hevc ? VAProfileHEVCMain +- : VAProfileH264ConstrainedBaseline; +-#else +- const VAProfile profile = VAProfileH264ConstrainedBaseline; +-#endif +- if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CBR, device)) +- obs_data_set_default_string(settings, "rate_control", "CBR"); +- else if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_VBR, device)) +- obs_data_set_default_string(settings, "rate_control", "VBR"); +- else +- obs_data_set_default_string(settings, "rate_control", "CQP"); +- +- vaapi_close_device(&drm_fd, va_dpy); +-} +- +-static void h264_vaapi_defaults(obs_data_t *settings) +-{ +- vaapi_defaults_internal(settings, false); +-} +- +-static void hevc_vaapi_defaults(obs_data_t *settings) +-{ +- vaapi_defaults_internal(settings, true); +-} +- +-static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, +- obs_data_t *settings) +-{ +- UNUSED_PARAMETER(p); +- +- const char *device = obs_data_get_string(settings, "vaapi_device"); +- int drm_fd = -1; +- VADisplay va_dpy = +- vaapi_open_device(&drm_fd, device, "vaapi_device_modified"); +- int profile = obs_data_get_int(settings, "profile"); +- obs_property_t *rc_p = obs_properties_get(ppts, "rate_control"); +- +- obs_property_list_clear(rc_p); +- +- if (!va_dpy) +- goto fail; +- +- switch (profile) { +- case FF_PROFILE_H264_CONSTRAINED_BASELINE: +- if (!vaapi_display_h264_supported(va_dpy, device)) +- goto fail; +- profile = VAProfileH264ConstrainedBaseline; +- break; +- case FF_PROFILE_H264_MAIN: +- if (!vaapi_display_h264_supported(va_dpy, device)) +- goto fail; +- profile = VAProfileH264Main; +- break; +- case FF_PROFILE_H264_HIGH: +- if (!vaapi_display_h264_supported(va_dpy, device)) +- goto fail; +- profile = VAProfileH264High; +- break; +-#ifdef ENABLE_HEVC +- case FF_PROFILE_HEVC_MAIN: +- if (!vaapi_display_hevc_supported(va_dpy, device)) +- goto fail; +- profile = VAProfileHEVCMain; +- break; +- case FF_PROFILE_HEVC_MAIN_10: +- if (!vaapi_display_hevc_supported(va_dpy, device)) +- goto fail; +- profile = VAProfileHEVCMain10; +- break; +-#endif +- } +- +- if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CBR, device)) +- obs_property_list_add_string(rc_p, "CBR (default)", "CBR"); +- +- if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_VBR, device)) +- obs_property_list_add_string(rc_p, "VBR", "VBR"); +- +- if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CQP, device)) +- obs_property_list_add_string(rc_p, "CQP", "CQP"); +- +-fail: +- vaapi_close_device(&drm_fd, va_dpy); +- return true; +-} +- +-static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p, +- obs_data_t *settings) +-{ +- UNUSED_PARAMETER(p); +- +- const char *rate_control = +- obs_data_get_string(settings, "rate_control"); +- +- const rc_mode_t *rc_mode = get_rc_mode(rate_control); +- +- /* Set options visibility per Rate Control */ +- set_visible(ppts, "qp", rc_mode->qp); +- set_visible(ppts, "bitrate", rc_mode->bitrate); +- set_visible(ppts, "maxrate", rc_mode->maxrate); +- +- return true; +-} +- +-static bool get_device_name_from_pci(struct pci_access *pacc, char *pci_slot, +- char *buf, int size) +-{ +- struct pci_filter filter; +- struct pci_dev *dev; +- char *name; +- +- pci_filter_init(pacc, &filter); +- if (pci_filter_parse_slot(&filter, pci_slot)) +- return false; +- +- pci_scan_bus(pacc); +- for (dev = pacc->devices; dev; dev = dev->next) { +- if (pci_filter_match(&filter, dev)) { +- pci_fill_info(dev, PCI_FILL_IDENT); +- name = pci_lookup_name(pacc, buf, size, +- PCI_LOOKUP_DEVICE, +- dev->vendor_id, dev->device_id); +- strcpy(buf, name); +- return true; +- } +- } +- return false; +-} +- +-static obs_properties_t *vaapi_properties_internal(bool hevc) +-{ +- obs_properties_t *props = obs_properties_create(); +- obs_property_t *list; +- +- list = obs_properties_add_list(props, "vaapi_device", +- obs_module_text("VAAPI.Device"), +- OBS_COMBO_TYPE_LIST, +- OBS_COMBO_FORMAT_STRING); +- if (os_file_exists("/dev/dri/by-path")) { +- os_dir_t *by_path_dir = os_opendir("/dev/dri/by-path"); +- struct pci_access *pacc = pci_alloc(); +- struct os_dirent *file; +- char namebuf[1024]; +- char pci_slot[13]; +- char *type; +- +- pci_init(pacc); +- while ((file = os_readdir(by_path_dir)) != NULL) { +- // file_name pattern: pci-- +- char *file_name = file->d_name; +- if (strcmp(file_name, ".") == 0 || +- strcmp(file_name, "..") == 0) +- continue; +- +- char path[64] = {0}; +- +- // Use the return value of snprintf to prevent truncation warning. +- int written = snprintf(path, 64, "/dev/dri/by-path/%s", +- file_name); +- if (written >= 64) +- blog(LOG_DEBUG, +- "obs-ffmpeg-vaapi: A format truncation may have occurred." +- " This can be ignored since it is quite improbable."); +- +- type = strrchr(file_name, '-'); +- if (type == NULL) +- continue; +- else +- type++; +- +- if (strcmp(type, "render") == 0) { +- strncpy(pci_slot, file_name + 4, 12); +- pci_slot[12] = 0; +- bool name_found = get_device_name_from_pci( +- pacc, pci_slot, namebuf, +- sizeof(namebuf)); +- +- if (!vaapi_device_h264_supported(path)) +- continue; +- +- if (!name_found) +- obs_property_list_add_string(list, path, +- path); +- else +- obs_property_list_add_string( +- list, namebuf, path); +- } +- } +- pci_cleanup(pacc); +- os_closedir(by_path_dir); +- } +- if (obs_property_list_item_count(list) == 0) { +- char path[32]; +- for (int i = 28;; i++) { +- snprintf(path, sizeof(path), "/dev/dri/renderD1%d", i); +- if (access(path, F_OK) == 0) { +- char card[128]; +- int ret = snprintf(card, sizeof(card), +- "Card%d: %s", i - 28, path); +- if (ret >= (int)sizeof(card)) +- blog(LOG_DEBUG, +- "obs-ffmpeg-vaapi: A format truncation may have occurred." +- " This can be ignored since it is quite improbable."); +- +- if (!vaapi_device_h264_supported(path)) +- continue; +- +- obs_property_list_add_string(list, card, path); +- } else { +- break; +- } +- } +- } +- +- obs_property_set_modified_callback(list, vaapi_device_modified); +- +- list = obs_properties_add_list(props, "profile", +- obs_module_text("Profile"), +- OBS_COMBO_TYPE_LIST, +- OBS_COMBO_FORMAT_INT); +- if (hevc) { +- obs_property_list_add_int(list, "Main", FF_PROFILE_HEVC_MAIN); +- obs_property_list_add_int(list, "Main10", +- FF_PROFILE_HEVC_MAIN_10); +- } else { +- obs_property_list_add_int(list, +- "Constrained Baseline (default)", +- FF_PROFILE_H264_CONSTRAINED_BASELINE); +- obs_property_list_add_int(list, "Main", FF_PROFILE_H264_MAIN); +- obs_property_list_add_int(list, "High", FF_PROFILE_H264_HIGH); +- } +- +- obs_property_set_modified_callback(list, vaapi_device_modified); +- +- list = obs_properties_add_list(props, "level", obs_module_text("Level"), +- OBS_COMBO_TYPE_LIST, +- OBS_COMBO_FORMAT_INT); +- obs_property_list_add_int(list, "Auto", FF_LEVEL_UNKNOWN); +- obs_property_list_add_int(list, "3.0", 30); +- obs_property_list_add_int(list, "3.1", 31); +- obs_property_list_add_int(list, "4.0 (default) (Compatibility mode)", +- 40); +- obs_property_list_add_int(list, "4.1", 41); +- obs_property_list_add_int(list, "4.2", 42); +- obs_property_list_add_int(list, "5.0", 50); +- obs_property_list_add_int(list, "5.1", 51); +- obs_property_list_add_int(list, "5.2", 52); +- +- list = obs_properties_add_list(props, "rate_control", +- obs_module_text("RateControl"), +- OBS_COMBO_TYPE_LIST, +- OBS_COMBO_FORMAT_STRING); +- +- obs_property_set_modified_callback(list, rate_control_modified); +- +- obs_property_t *p; +- p = obs_properties_add_int(props, "bitrate", obs_module_text("Bitrate"), +- 0, 300000, 50); +- obs_property_int_set_suffix(p, " Kbps"); +- +- p = obs_properties_add_int( +- props, "maxrate", obs_module_text("MaxBitrate"), 0, 300000, 50); +- obs_property_int_set_suffix(p, " Kbps"); +- +- obs_properties_add_int(props, "qp", "QP", 0, 51, 1); +- +- p = obs_properties_add_int(props, "keyint_sec", +- obs_module_text("KeyframeIntervalSec"), 0, +- 20, 1); +- obs_property_int_set_suffix(p, " s"); +- +- return props; +-} +- +-static obs_properties_t *h264_vaapi_properties(void *unused) +-{ +- UNUSED_PARAMETER(unused); +- return vaapi_properties_internal(false); +-} +- +-#ifdef ENABLE_HEVC +-static obs_properties_t *hevc_vaapi_properties(void *unused) +-{ +- UNUSED_PARAMETER(unused); +- return vaapi_properties_internal(true); +-} +-#endif +- +-static bool vaapi_extra_data(void *data, uint8_t **extra_data, size_t *size) +-{ +- struct vaapi_encoder *enc = data; +- +- *extra_data = enc->header; +- *size = enc->header_size; +- return true; +-} +- +-static bool vaapi_sei_data(void *data, uint8_t **extra_data, size_t *size) +-{ +- struct vaapi_encoder *enc = data; +- +- *extra_data = enc->sei; +- *size = enc->sei_size; +- return true; +-} +- +-struct obs_encoder_info h264_vaapi_encoder_info = { +- .id = "ffmpeg_vaapi", +- .type = OBS_ENCODER_VIDEO, +- .codec = "h264", +- .get_name = h264_vaapi_getname, +- .create = h264_vaapi_create, +- .destroy = vaapi_destroy, +- .encode = h264_vaapi_encode, +- .get_defaults = h264_vaapi_defaults, +- .get_properties = h264_vaapi_properties, +- .get_extra_data = vaapi_extra_data, +- .get_sei_data = vaapi_sei_data, +- .get_video_info = h264_vaapi_video_info, +-}; +- +-#ifdef ENABLE_HEVC +-struct obs_encoder_info hevc_vaapi_encoder_info = { +- .id = "hevc_ffmpeg_vaapi", +- .type = OBS_ENCODER_VIDEO, +- .codec = "hevc", +- .get_name = hevc_vaapi_getname, +- .create = hevc_vaapi_create, +- .destroy = vaapi_destroy, +- .encode = hevc_vaapi_encode, +- .get_defaults = hevc_vaapi_defaults, +- .get_properties = hevc_vaapi_properties, +- .get_extra_data = vaapi_extra_data, +- .get_sei_data = vaapi_sei_data, +- .get_video_info = hevc_vaapi_video_info, +-}; +-#endif +- +-#endif +diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c +index 92421c6..6a20937 100644 +--- a/plugins/obs-ffmpeg/obs-ffmpeg.c ++++ b/plugins/obs-ffmpeg/obs-ffmpeg.c +@@ -16,7 +16,6 @@ + LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 27, 100) + #include "vaapi-utils.h" + +-#define LIBAVUTIL_VAAPI_AVAILABLE + #endif + + OBS_DECLARE_MODULE() +@@ -46,13 +45,6 @@ extern struct obs_encoder_info hevc_nvenc_encoder_info; + extern struct obs_encoder_info svt_av1_encoder_info; + extern struct obs_encoder_info aom_av1_encoder_info; + +-#ifdef LIBAVUTIL_VAAPI_AVAILABLE +-extern struct obs_encoder_info h264_vaapi_encoder_info; +-#ifdef ENABLE_HEVC +-extern struct obs_encoder_info hevc_vaapi_encoder_info; +-#endif +-#endif +- + #ifndef __APPLE__ + + static const char *nvenc_check_name = "nvenc_check"; +@@ -330,33 +322,6 @@ static bool nvenc_supported(bool *out_h264, bool *out_hevc, bool *out_av1) + + #endif + +-#ifdef LIBAVUTIL_VAAPI_AVAILABLE +-static bool h264_vaapi_supported(void) +-{ +- const AVCodec *vaenc = avcodec_find_encoder_by_name("h264_vaapi"); +- +- if (!vaenc) +- return false; +- +- /* NOTE: If default device is NULL, it means there is no device +- * that support H264. */ +- return vaapi_get_h264_default_device() != NULL; +-} +-#ifdef ENABLE_HEVC +-static bool hevc_vaapi_supported(void) +-{ +- const AVCodec *vaenc = avcodec_find_encoder_by_name("hevc_vaapi"); +- +- if (!vaenc) +- return false; +- +- /* NOTE: If default device is NULL, it means there is no device +- * that support HEVC. */ +- return vaapi_get_hevc_default_device() != NULL; +-} +-#endif +-#endif +- + #ifdef _WIN32 + extern void jim_nvenc_load(bool h264, bool hevc, bool av1); + extern void jim_nvenc_unload(void); +@@ -440,30 +405,6 @@ bool obs_module_load(void) + #if defined(_WIN32) || defined(__linux__) + amf_load(); + #endif +- +-#ifdef LIBAVUTIL_VAAPI_AVAILABLE +- const char *libva_env = getenv("LIBVA_DRIVER_NAME"); +- if (!!libva_env) +- blog(LOG_WARNING, +- "LIBVA_DRIVER_NAME variable is set," +- " this could prevent FFmpeg VAAPI from working correctly"); +- +- if (h264_vaapi_supported()) { +- blog(LOG_INFO, "FFmpeg VAAPI H264 encoding supported"); +- obs_register_encoder(&h264_vaapi_encoder_info); +- } else { +- blog(LOG_INFO, "FFmpeg VAAPI H264 encoding not supported"); +- } +- +-#ifdef ENABLE_HEVC +- if (hevc_vaapi_supported()) { +- blog(LOG_INFO, "FFmpeg VAAPI HEVC encoding supported"); +- obs_register_encoder(&hevc_vaapi_encoder_info); +- } else { +- blog(LOG_INFO, "FFmpeg VAAPI HEVC encoding not supported"); +- } +-#endif +-#endif + #endif + + #if ENABLE_FFMPEG_LOGGING +-- +2.39.2 +