現(xiàn)自定義視頻編碼器?)
OBS Studio 如何用 obs_encoder_info 實(shí)現(xiàn)自定義視頻編碼器【免費(fèi)下載鏈接】obs-studioOBS Studio - Free and open source software for live streaming and screen recording項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ob/obs-studio如果你需要讓 OBS Studio 的推流/錄像輸出支持一個(gè)新的視頻編碼實(shí)現(xiàn)而不是替換整個(gè)輸出模塊正確的做法是編寫一個(gè)插件模塊用obs_encoder_info結(jié)構(gòu)體描述你的編碼器并在模塊加載時(shí)注冊(cè)到 libobs。本文基于倉庫內(nèi)的 插件開發(fā)文檔、編碼器 API 參考 以及內(nèi)置的 obs-x264 編碼器插件 源碼給出從定義編碼器結(jié)構(gòu)到注冊(cè)、構(gòu)建、驗(yàn)證的完整路徑。適用前提你能編譯 C/C 代碼并構(gòu)建 OBS 插件模塊插件機(jī)制文檔位于 docs/sphinx/plugins.rst編碼器專用頭文件是 libobs/obs-encoder.h。官方文檔說明編碼器的定位是OBS 專用的音視頻編碼器實(shí)現(xiàn)配合使用編碼器的輸出工作通常面向 h264/aac 這類流媒體與錄像場景。插件模塊的目錄結(jié)構(gòu)與 CMake 構(gòu)建插件模塊可以實(shí)現(xiàn)的 libobs 對(duì)象包括 sources、outputs、encoders 和 services。文檔給出的常規(guī)組織方式是一個(gè)文件負(fù)責(zé)插件初始化另外的文件分別定義各對(duì)象。對(duì)只包含一個(gè)編碼器的最小插件目錄可以是my-encoder-plugin/data/locale/en-US.ini my-encoder-plugin/CMakeLists.txt my-encoder-plugin/my-plugin.c my-encoder-plugin/my-encoder.c對(duì)應(yīng)的 CMakeLists.txt文檔示例見 plugins.rst# my-plugin/CMakeLists.txt project(my-plugin) set(my-plugin_SOURCES my-plugin.c my-encoder.c) add_library(my-plugin MODULE ${my-plugin_SOURCES}) target_link_libraries(my-plugin libobs) install_obs_plugin_with_data(my-plugin data)如果編碼器依賴第三方編解碼庫可以參考內(nèi)置 x264 插件的真實(shí) CMakeLists.txtcmake_minimum_required(VERSION 3.28...3.30) find_package(Libx264 REQUIRED) if(NOT TARGET OBS::opts-parser) add_subdirectory(${CMAKE_SOURCE_DIR}/shared/opts-parser ${CMAKE_BINARY_DIR}/shared/opts-parser) endif() add_library(obs-x264 MODULE) add_library(OBS::x264 ALIAS obs-x264) target_sources(obs-x264 PRIVATE obs-x264.c obs-x264-plugin-main.c) target_link_libraries(obs-x264 PRIVATE OBS::opts-parser Libx264::Libx264)它展示了三個(gè)要點(diǎn)用find_package定位外部依賴Libx264 REQUIRED、用add_library(... MODULE)產(chǎn)出動(dòng)態(tài)庫、用target_link_libraries鏈接依賴。填寫 obs_encoder_info 結(jié)構(gòu)體編碼器定義集中在 libobs/obs-encoder.h 的struct obs_encoder_info。按頭文件注釋字段分為Required implementation必選和Optional implementation可選兩部分必選字段字段說明id編碼器唯一字符串標(biāo)識(shí)文檔明確標(biāo)注 requiredtype編碼器類型視頻編碼器填OBS_ENCODER_VIDEO音頻填OBS_ENCODER_AUDIOcodec編解碼器字符串如 h264get_name返回編碼器的可翻譯名稱create用 settings 創(chuàng)建實(shí)現(xiàn)數(shù)據(jù)初始化失敗返回 NULLdestroy銷毀實(shí)現(xiàn)數(shù)據(jù)encode編碼音視頻幀輸出encoder_packetget_frame_size僅音頻編碼器使用返回每幀的采樣數(shù)如 AAC 為 1024可選字段視頻編碼器常用的get_defaults在 settings 上調(diào)用obs_data_set_default*系列函數(shù)設(shè)置默認(rèn)值、get_properties生成屬性列表前端可據(jù)此自動(dòng)生成設(shè)置界面、update更新設(shè)置通常用于運(yùn)行中改變碼率、get_extra_data通常返回編碼器頭數(shù)據(jù)、get_sei_data返回 SEI 數(shù)據(jù)、get_video_info告知后端輸入視頻需要轉(zhuǎn)換的格式或尺寸、caps能力標(biāo)志按位或組合。caps的取值直接來自 obs-encoder.h#define OBS_ENCODER_CAP_DEPRECATED (1 0) #define OBS_ENCODER_CAP_PASS_TEXTURE (1 1) #define OBS_ENCODER_CAP_DYN_BITRATE (1 2) #define OBS_ENCODER_CAP_INTERNAL (1 3) #define OBS_ENCODER_CAP_ROI (1 4) #define OBS_ENCODER_CAP_SCALING (1 5) #define OBS_ENCODER_CAP_MULTITRACK_DYN_BITRATE (1 6)文檔給出的最小示例編碼器示例代碼來自 plugins.rst/* my-encoder.c */ struct obs_encoder_info my_encoder { .id my_encoder, .type OBS_ENCODER_VIDEO, .codec h264, .get_name my_encoder_name, .create my_encoder_create, .destroy my_encoder_destroy, .encode my_encoder_encode, .update my_encoder_update, .get_extra_data my_encoder_extra_data, .get_sei_data my_encoder_sei_data, .get_video_info my_encoder_video_info };對(duì)照內(nèi)置 x264 編碼器的真實(shí)注冊(cè)結(jié)構(gòu)obs-x264.c可以看到完整字段組合struct obs_encoder_info obs_x264_encoder { .id obs_x264, .type OBS_ENCODER_VIDEO, .codec h264, .get_name obs_x264_getname, .create obs_x264_create, .destroy obs_x264_destroy, .encode obs_x264_encode, .update obs_x264_update, .get_properties obs_x264_props, .get_defaults obs_x264_defaults, .get_extra_data obs_x264_extra_data, .get_sei_data obs_x264_sei, .get_video_info obs_x264_video_info, .caps OBS_ENCODER_CAP_DYN_BITRATE | OBS_ENCODER_CAP_ROI, };兩個(gè)實(shí)現(xiàn)細(xì)節(jié)值得注意get_properties的data參數(shù)可能為 NULL——當(dāng)對(duì)編碼器類型而不是某個(gè)實(shí)例調(diào)用obs_get_encoder_properties()時(shí)會(huì)發(fā)生文檔要求實(shí)現(xiàn)方妥善處理這一情況。encode的返回值語義true表示成功false表示 critical failure嚴(yán)重失敗。encode 回調(diào)與 encoder_packetencode的原型是bool (*encode)(void *data, struct encoder_frame *frame, struct encoder_packet *packet, bool *received_packet)。輸入幀結(jié)構(gòu) encoder_frame 包含原始數(shù)據(jù)平面data[MAX_AV_PLANES]、每個(gè)平面的行步長linesize、音頻幀數(shù)frames僅音頻和呈現(xiàn)時(shí)間戳pts。輸出要填寫 encoder_packet其中由編碼器實(shí)現(xiàn)方負(fù)責(zé)設(shè)置的字段是data、size、pts、dts、timebase_num、timebase_den、type填OBS_ENCODER_VIDEO和keyframe。文檔明確標(biāo)注以下字段should not be set by the encoder implementation由 libobs 內(nèi)部填充dts_usec、sys_dts_usec、priority已不再使用、drop_priority、track_idx、encoder。*received_packet需要你在每次調(diào)用中顯式設(shè)置本次調(diào)用是否產(chǎn)出了一個(gè) packet。內(nèi)置 x264 編碼器的處理方式obs-x264.c*received_packet (nal_count ! 0); parse_packet(obsx264, packet, nals, nal_count, pic_out); return true;即按實(shí)際產(chǎn)出的 NAL 數(shù)量決定是否置位received_packet隨后填充 packet 并返回true。另外如果編碼器運(yùn)行中會(huì)輸出頭數(shù)據(jù)如 SPS/PPS實(shí)現(xiàn)get_extra_data返回true并填好extra_data與size沒有頭數(shù)據(jù)時(shí)返回false。x264 的實(shí)現(xiàn)obs-x264.c就是在上下文存在時(shí)返回緩存的extra_data否則返回false。在 obs_module_load 中注冊(cè)編碼器插件初始化文件的職責(zé)是聲明模塊并在obs_module_load()中注冊(cè)對(duì)象。內(nèi)置 x264 插件的完整初始化文件只有 16 行obs-x264-plugin-main.c#include obs-module.h OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE(obs-x264, en-US) MODULE_EXPORT const char *obs_module_description(void) { return x264 based encoder; } extern struct obs_encoder_info obs_x264_encoder; bool obs_module_load(void) { obs_register_encoder(obs_x264_encoder); return true; }要點(diǎn)#include obs-module.h會(huì)自動(dòng)引入obs.h而obs.h又自動(dòng)包含obs-encoder.h、obs-data.h、obs-properties.h等所以編碼器插件不需要單獨(dú) include 編碼器頭文件見 plugins.rst 的 Plugin Module Headers 一節(jié)。obs_register_encoder()通常在obs_module_load()中調(diào)用。宏obs_register_encoder(info)實(shí)際展開為obs_register_encoder_s(info, sizeof(struct obs_encoder_info))見 obs-encoder.h按結(jié)構(gòu)體大小注冊(cè)以兼容結(jié)構(gòu)體擴(kuò)展。obs_module_load()的返回值就是模塊加載判定返回true繼續(xù)加載模塊返回false表示失敗并觸發(fā)模塊卸載reference-modules.rst。如何驗(yàn)證編碼器注冊(cè)成功文檔提供的驗(yàn)證路徑分兩層模塊加載層面前端通過obs_open_module()打開模塊鏡像通過obs_init_module()觸發(fā)obs_module_load()。obs_open_module會(huì)返回明確的失敗碼包括MODULE_SUCCESS、MODULE_FILE_NOT_FOUND找不到模塊、MODULE_MISSING_EXPORTS缺少必需導(dǎo)出函數(shù)、MODULE_INCOMPATIBLE_VER版本不兼容等obs_init_module返回true表示模塊加載成功。如果你的obs_module_load里注冊(cè)邏輯出錯(cuò)并返回false模塊會(huì)被卸載這一條就是最基本的失敗信號(hào)。編碼器對(duì)象層面注冊(cè)完成后可以用 reference-encoders.rst 中的類型級(jí)接口按id反查編碼器obs_encoder_defaults(id)取默認(rèn)設(shè)置、obs_get_encoder_properties(id)取屬性列表、obs_get_encoder_type(id)確認(rèn)類型最終用obs_video_encoder_create(id, name, settings, hotkey_data)創(chuàng)建編碼器實(shí)例創(chuàng)建失敗會(huì)返回NULL。也就是說obs_video_encoder_create對(duì)你的id能返回非 NULL說明注冊(cè)、create回調(diào)整條鏈路都工作正常。設(shè)置命名約定與能力聲明的邊界文檔plugins.rst 的 IMPORTANT NOTE對(duì)編碼器的通用設(shè)置項(xiàng)給出了命名約定實(shí)現(xiàn)時(shí)應(yīng)遵守以便輸出模塊和前端正確識(shí)別設(shè)置名適用含義bitrate視頻與音頻編碼器碼率單位為千比特kilobitsrate_control視頻編碼器碼率控制方式至少應(yīng)提供 CBR其他常見值為 VBR、CQPkeyint_sec視頻編碼器關(guān)鍵幀間隔單位為秒或最接近的近似值兩條邊界需要明確頭文件注釋obs-encoder.h說明編碼器的使用范圍是有限且特定的一般面向流媒體和錄像場景的 h264/aac 實(shí)現(xiàn)如果你的目標(biāo)不屬于這類用途文檔沒有給出支持承諾。OBS_ENCODER_CAP_SCALING表示編碼器自行實(shí)現(xiàn)縮放邏輯、希望接收未縮放的輸入幀OBS_ENCODER_CAP_ROI表示支持感興趣區(qū)域ROI自 30.1 版本引入見 reference-encoders.rst 的obs_encoder_roi部分。這些能力標(biāo)志聲明后對(duì)應(yīng)的行為如 ROI 區(qū)域在開啟縮放時(shí)按縮放后尺寸回調(diào)由 libobs 按聲明調(diào)用不能只聲明標(biāo)志而不在實(shí)現(xiàn)中處理。完成以上步驟后你的編碼器插件在 OBS 構(gòu)建中作為MODULE動(dòng)態(tài)庫產(chǎn)出并隨插件目錄安裝前端加載插件目錄中的模塊文件即會(huì)觸發(fā)注冊(cè)后續(xù)深入可參考 obs-outputs 插件 中消費(fèi)編碼后 packet 的輸出實(shí)現(xiàn)理解編碼數(shù)據(jù)如何流向最終輸出?!久赓M(fèi)下載鏈接】obs-studioOBS Studio - Free and open source software for live streaming and screen recording項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ob/obs-studio創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考