mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-09-20 04:42:18 +02:00
obs-ffmpeg: Implement texture encoding for VAAPI
This commit is contained in:
parent
65295eaf93
commit
06e364b670
@ -66,6 +66,7 @@ target_link_libraries(
|
||||
$<$<PLATFORM_ID:Linux,FreeBSD,OpenBSD>:Libva::va>
|
||||
$<$<PLATFORM_ID:Linux,FreeBSD,OpenBSD>:Libva::drm>
|
||||
$<$<PLATFORM_ID:Linux,FreeBSD,OpenBSD>:Libpci::pci>
|
||||
$<$<PLATFORM_ID:Linux,FreeBSD,OpenBSD>:Libdrm::Libdrm>
|
||||
$<$<BOOL:${ENABLE_NEW_MPEGTS_OUTPUT}>:Librist::Librist>
|
||||
$<$<BOOL:${ENABLE_NEW_MPEGTS_OUTPUT}>:Libsrt::Libsrt>)
|
||||
|
||||
|
@ -33,6 +33,7 @@ elseif(
|
||||
OR OS_OPENBSD)
|
||||
find_package(Libva REQUIRED)
|
||||
find_package(Libpci REQUIRED)
|
||||
find_package(Libdrm REQUIRED)
|
||||
endif()
|
||||
|
||||
if(OS_WINDOWS OR (OS_LINUX AND ENABLE_NATIVE_NVENC))
|
||||
|
@ -111,8 +111,9 @@ if(OS_WINDOWS)
|
||||
elseif(OS_POSIX AND NOT OS_MACOS)
|
||||
find_package(Libva REQUIRED)
|
||||
find_package(Libpci REQUIRED)
|
||||
find_package(Libdrm REQUIRED)
|
||||
target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c vaapi-utils.h)
|
||||
target_link_libraries(obs-ffmpeg PRIVATE Libva::va Libva::drm LIBPCI::LIBPCI)
|
||||
target_link_libraries(obs-ffmpeg PRIVATE Libva::va Libva::drm LIBPCI::LIBPCI Libdrm::Libdrm)
|
||||
|
||||
if(ENABLE_NATIVE_NVENC)
|
||||
find_package(FFnvcodec 12.0.0.0...<12.2.0.0 REQUIRED)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/hwcontext.h>
|
||||
#include <libavutil/hwcontext_vaapi.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavfilter/avfilter.h>
|
||||
@ -44,6 +45,9 @@
|
||||
#include "vaapi-utils.h"
|
||||
#include "obs-ffmpeg-formats.h"
|
||||
|
||||
#include <va/va_drmcommon.h>
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
|
||||
#define do_log(level, format, ...) \
|
||||
blog(level, "[FFmpeg VAAPI encoder: '%s'] " format, \
|
||||
obs_encoder_get_name(enc->encoder), ##__VA_ARGS__)
|
||||
@ -58,12 +62,19 @@ enum codec_type {
|
||||
CODEC_AV1,
|
||||
};
|
||||
|
||||
struct vaapi_surface {
|
||||
AVFrame *frame;
|
||||
gs_texture_t *textures[4];
|
||||
uint32_t num_textures;
|
||||
};
|
||||
|
||||
struct vaapi_encoder {
|
||||
obs_encoder_t *encoder;
|
||||
enum codec_type codec;
|
||||
|
||||
AVBufferRef *vadevice_ref;
|
||||
AVBufferRef *vaframes_ref;
|
||||
VADisplay va_dpy;
|
||||
|
||||
const AVCodec *vaapi;
|
||||
AVCodecContext *context;
|
||||
@ -146,6 +157,11 @@ static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path)
|
||||
return false;
|
||||
}
|
||||
|
||||
AVHWDeviceContext *vahwctx =
|
||||
(AVHWDeviceContext *)enc->vadevice_ref->data;
|
||||
AVVAAPIDeviceContext *vadevctx = vahwctx->hwctx;
|
||||
enc->va_dpy = vadevctx->display;
|
||||
|
||||
enc->vaframes_ref = av_hwframe_ctx_alloc(enc->vadevice_ref);
|
||||
if (!enc->vaframes_ref) {
|
||||
warn("Failed to alloc HW frames context");
|
||||
@ -158,7 +174,6 @@ static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path)
|
||||
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) {
|
||||
@ -376,6 +391,117 @@ static bool vaapi_update(void *data, obs_data_t *settings)
|
||||
return vaapi_init_codec(enc, device);
|
||||
}
|
||||
|
||||
static inline enum gs_color_format drm_to_gs_color_format(int format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_R8:
|
||||
return GS_R8;
|
||||
case DRM_FORMAT_R16:
|
||||
return GS_R16;
|
||||
case DRM_FORMAT_GR88:
|
||||
return GS_R8G8;
|
||||
case DRM_FORMAT_GR1616:
|
||||
return GS_RG16;
|
||||
default:
|
||||
blog(LOG_ERROR, "Unsupported DRM format %d", format);
|
||||
return GS_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void vaapi_destroy_surface(struct vaapi_surface *out)
|
||||
{
|
||||
obs_enter_graphics();
|
||||
|
||||
for (uint32_t i = 0; i < out->num_textures; ++i) {
|
||||
if (out->textures[i]) {
|
||||
gs_texture_destroy(out->textures[i]);
|
||||
out->textures[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
obs_leave_graphics();
|
||||
|
||||
av_frame_free(&out->frame);
|
||||
}
|
||||
|
||||
static bool vaapi_create_surface(struct vaapi_encoder *enc,
|
||||
struct vaapi_surface *out)
|
||||
{
|
||||
int ret;
|
||||
VAStatus vas;
|
||||
VADRMPRIMESurfaceDescriptor desc;
|
||||
const AVPixFmtDescriptor *fmt_desc;
|
||||
bool ok = true;
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
fmt_desc = av_pix_fmt_desc_get(enc->context->pix_fmt);
|
||||
if (!fmt_desc) {
|
||||
warn("Failed to get pix fmt descriptor");
|
||||
return false;
|
||||
}
|
||||
|
||||
out->frame = av_frame_alloc();
|
||||
if (!out->frame) {
|
||||
warn("Failed to allocate hw frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = av_hwframe_get_buffer(enc->vaframes_ref, out->frame, 0);
|
||||
if (ret < 0) {
|
||||
warn("Failed to get hw frame buffer: %s", av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vas = vaExportSurfaceHandle(enc->va_dpy, (uintptr_t)out->frame->data[3],
|
||||
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
|
||||
VA_EXPORT_SURFACE_WRITE_ONLY |
|
||||
VA_EXPORT_SURFACE_SEPARATE_LAYERS,
|
||||
&desc);
|
||||
if (vas != VA_STATUS_SUCCESS) {
|
||||
warn("Failed to export VA surface handle: %s", vaErrorStr(vas));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
obs_enter_graphics();
|
||||
|
||||
for (uint32_t i = 0; i < desc.num_layers; ++i) {
|
||||
unsigned int width = desc.width;
|
||||
unsigned int height = desc.height;
|
||||
if (i) {
|
||||
width /= 1 << fmt_desc->log2_chroma_w;
|
||||
height /= 1 << fmt_desc->log2_chroma_h;
|
||||
}
|
||||
|
||||
out->textures[i] = gs_texture_create_from_dmabuf(
|
||||
width, height, desc.layers[i].drm_format,
|
||||
drm_to_gs_color_format(desc.layers[i].drm_format), 1,
|
||||
&desc.objects[desc.layers[i].object_index[0]].fd,
|
||||
&desc.layers[i].pitch[0], &desc.layers[i].offset[0],
|
||||
&desc.objects[desc.layers[i].object_index[0]]
|
||||
.drm_format_modifier);
|
||||
|
||||
if (!out->textures[i]) {
|
||||
warn("Failed to import VA surface texture");
|
||||
ok = false;
|
||||
}
|
||||
|
||||
out->num_textures++;
|
||||
}
|
||||
|
||||
obs_leave_graphics();
|
||||
|
||||
for (uint32_t i = 0; i < desc.num_objects; ++i)
|
||||
close(desc.objects[i].fd);
|
||||
|
||||
if (ok)
|
||||
return true;
|
||||
|
||||
fail:
|
||||
vaapi_destroy_surface(out);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void flush_remaining_packets(struct vaapi_encoder *enc)
|
||||
{
|
||||
int r_pkt = 1;
|
||||
@ -457,21 +583,72 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool vaapi_test_texencode(struct vaapi_encoder *enc)
|
||||
{
|
||||
struct vaapi_surface surface;
|
||||
|
||||
if (obs_encoder_scaling_enabled(enc->encoder) &&
|
||||
!obs_encoder_gpu_scaling_enabled(enc->encoder))
|
||||
return false;
|
||||
|
||||
if (!vaapi_create_surface(enc, &surface))
|
||||
return false;
|
||||
|
||||
vaapi_destroy_surface(&surface);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void *vaapi_create_tex_internal(obs_data_t *settings,
|
||||
obs_encoder_t *encoder,
|
||||
enum codec_type codec,
|
||||
const char *fallback)
|
||||
{
|
||||
void *enc = vaapi_create_internal(settings, encoder, codec);
|
||||
if (!enc) {
|
||||
return NULL;
|
||||
}
|
||||
if (!vaapi_test_texencode(enc)) {
|
||||
vaapi_destroy(enc);
|
||||
blog(LOG_WARNING, "VAAPI: Falling back to %s encoder",
|
||||
fallback);
|
||||
return obs_encoder_create_rerouted(encoder, fallback);
|
||||
}
|
||||
return enc;
|
||||
}
|
||||
|
||||
static void *h264_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
{
|
||||
return vaapi_create_internal(settings, encoder, CODEC_H264);
|
||||
}
|
||||
|
||||
static void *h264_vaapi_create_tex(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
{
|
||||
return vaapi_create_tex_internal(settings, encoder, CODEC_H264,
|
||||
"ffmpeg_vaapi");
|
||||
}
|
||||
|
||||
static void *av1_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
{
|
||||
return vaapi_create_internal(settings, encoder, CODEC_AV1);
|
||||
}
|
||||
|
||||
static void *av1_vaapi_create_tex(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
{
|
||||
return vaapi_create_tex_internal(settings, encoder, CODEC_AV1,
|
||||
"av1_ffmpeg_vaapi");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_HEVC
|
||||
static void *hevc_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
{
|
||||
return vaapi_create_internal(settings, encoder, CODEC_HEVC);
|
||||
}
|
||||
|
||||
static void *hevc_vaapi_create_tex(obs_data_t *settings, obs_encoder_t *encoder)
|
||||
{
|
||||
return vaapi_create_tex_internal(settings, encoder, CODEC_HEVC,
|
||||
"hevc_ffmpeg_vaapi");
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void copy_data(AVFrame *pic, const struct encoder_frame *frame,
|
||||
@ -500,49 +677,14 @@ static inline void copy_data(AVFrame *pic, const struct encoder_frame *frame,
|
||||
}
|
||||
}
|
||||
|
||||
static bool vaapi_encode(void *data, struct encoder_frame *frame,
|
||||
struct encoder_packet *packet, bool *received_packet)
|
||||
static bool vaapi_encode_internal(struct vaapi_encoder *enc, AVFrame *frame,
|
||||
struct encoder_packet *packet,
|
||||
bool *received_packet)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
ret = avcodec_send_frame(enc->context, hwframe);
|
||||
ret = avcodec_send_frame(enc->context, frame);
|
||||
if (ret == 0 || ret == AVERROR(EAGAIN))
|
||||
ret = avcodec_receive_packet(enc->context, enc->packet);
|
||||
|
||||
@ -619,11 +761,63 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
|
||||
obs_av1_keyframe(packet->data, packet->size);
|
||||
}
|
||||
*received_packet = true;
|
||||
} else {
|
||||
*received_packet = false;
|
||||
}
|
||||
|
||||
av_packet_unref(enc->packet);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
av_packet_unref(enc->packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool vaapi_encode_copy(void *data, struct encoder_frame *frame,
|
||||
struct encoder_packet *packet,
|
||||
bool *received_packet)
|
||||
{
|
||||
struct vaapi_encoder *enc = data;
|
||||
AVFrame *hwframe = NULL;
|
||||
int ret;
|
||||
|
||||
*received_packet = false;
|
||||
|
||||
hwframe = av_frame_alloc();
|
||||
if (!hwframe) {
|
||||
warn("vaapi_encode_copy: failed to allocate hw frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = av_hwframe_get_buffer(enc->vaframes_ref, hwframe, 0);
|
||||
if (ret < 0) {
|
||||
warn("vaapi_encode_copy: 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_copy: 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_copy: failed to copy props to hw frame: %s",
|
||||
av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vaapi_encode_internal(enc, hwframe, packet, received_packet))
|
||||
goto fail;
|
||||
|
||||
av_frame_free(&hwframe);
|
||||
return true;
|
||||
|
||||
@ -632,6 +826,59 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool vaapi_encode_tex(void *data, struct encoder_texture *texture,
|
||||
int64_t pts, uint64_t lock_key, uint64_t *next_key,
|
||||
struct encoder_packet *packet,
|
||||
bool *received_packet)
|
||||
{
|
||||
UNUSED_PARAMETER(lock_key);
|
||||
UNUSED_PARAMETER(next_key);
|
||||
|
||||
struct vaapi_encoder *enc = data;
|
||||
struct vaapi_surface surface;
|
||||
int ret;
|
||||
|
||||
*received_packet = false;
|
||||
|
||||
if (!vaapi_create_surface(enc, &surface)) {
|
||||
warn("vaapi_encode_tex: failed to create texture hw frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
obs_enter_graphics();
|
||||
|
||||
for (uint32_t i = 0; i < surface.num_textures; ++i) {
|
||||
if (!texture->tex[i]) {
|
||||
warn("vaapi_encode_tex: unexpected number of textures");
|
||||
goto fail;
|
||||
}
|
||||
gs_copy_texture(surface.textures[i], texture->tex[i]);
|
||||
}
|
||||
|
||||
gs_flush();
|
||||
|
||||
obs_leave_graphics();
|
||||
|
||||
enc->vframe->pts = pts;
|
||||
|
||||
ret = av_frame_copy_props(surface.frame, enc->vframe);
|
||||
if (ret < 0) {
|
||||
warn("vaapi_encode_tex: failed to copy props to hw frame: %s",
|
||||
av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vaapi_encode_internal(enc, surface.frame, packet, received_packet))
|
||||
goto fail;
|
||||
|
||||
vaapi_destroy_surface(&surface);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
vaapi_destroy_surface(&surface);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void set_visible(obs_properties_t *ppts, const char *name, bool visible)
|
||||
{
|
||||
obs_property_t *p = obs_properties_get(ppts, name);
|
||||
@ -1047,12 +1294,29 @@ struct obs_encoder_info h264_vaapi_encoder_info = {
|
||||
.get_name = h264_vaapi_getname,
|
||||
.create = h264_vaapi_create,
|
||||
.destroy = vaapi_destroy,
|
||||
.encode = vaapi_encode,
|
||||
.encode = vaapi_encode_copy,
|
||||
.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 = vaapi_video_info,
|
||||
.caps = OBS_ENCODER_CAP_INTERNAL,
|
||||
};
|
||||
|
||||
struct obs_encoder_info h264_vaapi_encoder_tex_info = {
|
||||
.id = "ffmpeg_vaapi_tex",
|
||||
.type = OBS_ENCODER_VIDEO,
|
||||
.codec = "h264",
|
||||
.get_name = h264_vaapi_getname,
|
||||
.create = h264_vaapi_create_tex,
|
||||
.destroy = vaapi_destroy,
|
||||
.encode_texture2 = vaapi_encode_tex,
|
||||
.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 = vaapi_video_info,
|
||||
.caps = OBS_ENCODER_CAP_PASS_TEXTURE,
|
||||
};
|
||||
|
||||
struct obs_encoder_info av1_vaapi_encoder_info = {
|
||||
@ -1062,12 +1326,29 @@ struct obs_encoder_info av1_vaapi_encoder_info = {
|
||||
.get_name = av1_vaapi_getname,
|
||||
.create = av1_vaapi_create,
|
||||
.destroy = vaapi_destroy,
|
||||
.encode = vaapi_encode,
|
||||
.encode = vaapi_encode_copy,
|
||||
.get_defaults = av1_vaapi_defaults,
|
||||
.get_properties = av1_vaapi_properties,
|
||||
.get_extra_data = vaapi_extra_data,
|
||||
.get_sei_data = vaapi_sei_data,
|
||||
.get_video_info = vaapi_video_info,
|
||||
.caps = OBS_ENCODER_CAP_INTERNAL,
|
||||
};
|
||||
|
||||
struct obs_encoder_info av1_vaapi_encoder_tex_info = {
|
||||
.id = "av1_ffmpeg_vaapi_tex",
|
||||
.type = OBS_ENCODER_VIDEO,
|
||||
.codec = "av1",
|
||||
.get_name = av1_vaapi_getname,
|
||||
.create = av1_vaapi_create_tex,
|
||||
.destroy = vaapi_destroy,
|
||||
.encode_texture2 = vaapi_encode_tex,
|
||||
.get_defaults = av1_vaapi_defaults,
|
||||
.get_properties = av1_vaapi_properties,
|
||||
.get_extra_data = vaapi_extra_data,
|
||||
.get_sei_data = vaapi_sei_data,
|
||||
.get_video_info = vaapi_video_info,
|
||||
.caps = OBS_ENCODER_CAP_PASS_TEXTURE,
|
||||
};
|
||||
|
||||
#ifdef ENABLE_HEVC
|
||||
@ -1078,11 +1359,28 @@ struct obs_encoder_info hevc_vaapi_encoder_info = {
|
||||
.get_name = hevc_vaapi_getname,
|
||||
.create = hevc_vaapi_create,
|
||||
.destroy = vaapi_destroy,
|
||||
.encode = vaapi_encode,
|
||||
.encode = vaapi_encode_copy,
|
||||
.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 = vaapi_video_info,
|
||||
.caps = OBS_ENCODER_CAP_INTERNAL,
|
||||
};
|
||||
|
||||
struct obs_encoder_info hevc_vaapi_encoder_tex_info = {
|
||||
.id = "hevc_ffmpeg_vaapi_tex",
|
||||
.type = OBS_ENCODER_VIDEO,
|
||||
.codec = "hevc",
|
||||
.get_name = hevc_vaapi_getname,
|
||||
.create = hevc_vaapi_create_tex,
|
||||
.destroy = vaapi_destroy,
|
||||
.encode_texture2 = vaapi_encode_tex,
|
||||
.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 = vaapi_video_info,
|
||||
.caps = OBS_ENCODER_CAP_PASS_TEXTURE,
|
||||
};
|
||||
#endif
|
||||
|
@ -50,9 +50,12 @@ extern struct obs_encoder_info aom_av1_encoder_info;
|
||||
|
||||
#ifdef LIBAVUTIL_VAAPI_AVAILABLE
|
||||
extern struct obs_encoder_info h264_vaapi_encoder_info;
|
||||
extern struct obs_encoder_info h264_vaapi_encoder_tex_info;
|
||||
extern struct obs_encoder_info av1_vaapi_encoder_info;
|
||||
extern struct obs_encoder_info av1_vaapi_encoder_tex_info;
|
||||
#ifdef ENABLE_HEVC
|
||||
extern struct obs_encoder_info hevc_vaapi_encoder_info;
|
||||
extern struct obs_encoder_info hevc_vaapi_encoder_tex_info;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -404,6 +407,7 @@ bool obs_module_load(void)
|
||||
if (h264_vaapi_supported()) {
|
||||
blog(LOG_INFO, "FFmpeg VAAPI H264 encoding supported");
|
||||
obs_register_encoder(&h264_vaapi_encoder_info);
|
||||
obs_register_encoder(&h264_vaapi_encoder_tex_info);
|
||||
} else {
|
||||
blog(LOG_INFO, "FFmpeg VAAPI H264 encoding not supported");
|
||||
}
|
||||
@ -411,6 +415,7 @@ bool obs_module_load(void)
|
||||
if (av1_vaapi_supported()) {
|
||||
blog(LOG_INFO, "FFmpeg VAAPI AV1 encoding supported");
|
||||
obs_register_encoder(&av1_vaapi_encoder_info);
|
||||
obs_register_encoder(&av1_vaapi_encoder_tex_info);
|
||||
} else {
|
||||
blog(LOG_INFO, "FFmpeg VAAPI AV1 encoding not supported");
|
||||
}
|
||||
@ -419,6 +424,7 @@ bool obs_module_load(void)
|
||||
if (hevc_vaapi_supported()) {
|
||||
blog(LOG_INFO, "FFmpeg VAAPI HEVC encoding supported");
|
||||
obs_register_encoder(&hevc_vaapi_encoder_info);
|
||||
obs_register_encoder(&hevc_vaapi_encoder_tex_info);
|
||||
} else {
|
||||
blog(LOG_INFO, "FFmpeg VAAPI HEVC encoding not supported");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user