feat(encode): add Jetson Multimedia API encoder backend

Integrate a native Jetson Multimedia API encoder path and keep the existing encoded access-unit contract for RTMP, RTP, and recording consumers.

This adds conditional Jetson MMAPI detection in CMake, builds the required NVIDIA sample common classes into a dedicated support library, and compiles the new backend only when the platform dependencies are present.

The runtime selector now lets encoder.backend=auto prefer Jetson MM for NVIDIA hardware requests while keeping encoder.backend=ffmpeg as an explicit FFmpeg path. Device selection semantics are updated so nvidia requires the Jetson backend, auto can fall back to FFmpeg software, and software remains FFmpeg-only.

The Jetson backend converts supported raw inputs through swscale, feeds NvVideoEncoder in YUV420M, emits Annex-B access units, and harvests decoder configuration from a warmup keyframe so downstream packetizers keep their existing contract.

This also splits FFmpeg encoder option handling into a shared header, updates runtime config/help text and tester defaults, and refreshes compatibility/caveat documentation to reflect the new selection behavior.

Build-tree runtime RPATH handling is tightened so GCC 15 builds keep the matching libstdc++ visible locally. Verification covered GCC 15 builds, RTP H.264/H.265 tester runs, RTMP H.264 stub publish, local live SRS smoke with cvmmap://zed1, and remote execution on 192.168.2.155 using the deployed bundle lib directory for the GCC 15 runtime.
This commit is contained in:
2026-04-15 18:37:44 +08:00
parent 16a1a38645
commit 51d03d4279
12 changed files with 1538 additions and 323 deletions
+101 -6
View File
@@ -8,6 +8,9 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(GNUInstallDirs)
set(CVMMAP_STREAMER_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
function(cvmmap_streamer_append_runtime_dir out_var runtime_library)
execute_process(
COMMAND "${CMAKE_CXX_COMPILER}" -print-file-name=${runtime_library}
@@ -69,6 +72,17 @@ set(
"${CMAKE_CURRENT_LIST_DIR}/third_party/mcap/include"
CACHE PATH
"Path to MCAP headers")
set(
CVMMAP_STREAMER_ENABLE_JETSON_MM
"AUTO"
CACHE STRING
"Enable Jetson Multimedia API encoder backend: AUTO, ON, or OFF")
set_property(CACHE CVMMAP_STREAMER_ENABLE_JETSON_MM PROPERTY STRINGS AUTO ON OFF)
set(
CVMMAP_STREAMER_JETSON_MMAPI_ROOT
"/usr/src/jetson_multimedia_api"
CACHE PATH
"Path to the Jetson Multimedia API root")
find_package(Threads REQUIRED)
find_package(OpenSSL REQUIRED)
@@ -117,7 +131,7 @@ if (CVMMAP_CNATS_PROVIDER STREQUAL "system")
find_package(cnats CONFIG REQUIRED)
find_package(cvmmap-core CONFIG QUIET PATHS "${CVMMAP_LOCAL_CORE_DIR}" NO_DEFAULT_PATH)
if (NOT TARGET cvmmap::client)
find_package(cvmmap-core CONFIG QUIET)
find_package(cvmmap-core CONFIG REQUIRED PATHS "${CVMMAP_LOCAL_CORE_DIR}" NO_DEFAULT_PATH)
endif()
else()
if (NOT EXISTS "${CVMMAP_LOCAL_NATS_STATIC}")
@@ -240,6 +254,78 @@ else()
set(CVMMAP_STREAMER_HAS_MCAP_DEPTH 0)
endif()
set(_CVMMAP_STREAMER_JETSON_MM_INCLUDE_DIR "${CVMMAP_STREAMER_JETSON_MMAPI_ROOT}/include")
set(_CVMMAP_STREAMER_JETSON_MM_COMMON_DIR "${CVMMAP_STREAMER_JETSON_MMAPI_ROOT}/samples/common/classes")
set(_CVMMAP_STREAMER_JETSON_MM_COMMON_SOURCES
"${_CVMMAP_STREAMER_JETSON_MM_COMMON_DIR}/NvBuffer.cpp"
"${_CVMMAP_STREAMER_JETSON_MM_COMMON_DIR}/NvElement.cpp"
"${_CVMMAP_STREAMER_JETSON_MM_COMMON_DIR}/NvElementProfiler.cpp"
"${_CVMMAP_STREAMER_JETSON_MM_COMMON_DIR}/NvLogging.cpp"
"${_CVMMAP_STREAMER_JETSON_MM_COMMON_DIR}/NvV4l2Element.cpp"
"${_CVMMAP_STREAMER_JETSON_MM_COMMON_DIR}/NvV4l2ElementPlane.cpp"
"${_CVMMAP_STREAMER_JETSON_MM_COMMON_DIR}/NvVideoEncoder.cpp")
set(_CVMMAP_STREAMER_JETSON_MM_MISSING_DEPS)
if (NOT EXISTS "${_CVMMAP_STREAMER_JETSON_MM_INCLUDE_DIR}/NvVideoEncoder.h")
list(APPEND _CVMMAP_STREAMER_JETSON_MM_MISSING_DEPS
"Jetson Multimedia API headers at ${_CVMMAP_STREAMER_JETSON_MM_INCLUDE_DIR}")
endif()
foreach(_cvmmap_streamer_jetson_mm_source IN LISTS _CVMMAP_STREAMER_JETSON_MM_COMMON_SOURCES)
if (NOT EXISTS "${_cvmmap_streamer_jetson_mm_source}")
list(APPEND _CVMMAP_STREAMER_JETSON_MM_MISSING_DEPS
"Jetson Multimedia API common source ${_cvmmap_streamer_jetson_mm_source}")
endif()
endforeach()
find_library(
CVMMAP_STREAMER_NVBUFSURFACE_LIBRARY
NAMES nvbufsurface
PATHS
/usr/lib/aarch64-linux-gnu/nvidia
/usr/lib/aarch64-linux-gnu/tegra
/usr/lib/aarch64-linux-gnu
PATH_SUFFIXES nvidia tegra)
if (NOT CVMMAP_STREAMER_NVBUFSURFACE_LIBRARY)
list(APPEND _CVMMAP_STREAMER_JETSON_MM_MISSING_DEPS "libnvbufsurface")
endif()
find_library(CVMMAP_STREAMER_LIBV4L2_LIBRARY NAMES v4l2)
if (NOT CVMMAP_STREAMER_LIBV4L2_LIBRARY)
list(APPEND _CVMMAP_STREAMER_JETSON_MM_MISSING_DEPS "libv4l2")
endif()
if (_CVMMAP_STREAMER_JETSON_MM_MISSING_DEPS)
list(JOIN _CVMMAP_STREAMER_JETSON_MM_MISSING_DEPS ", " _CVMMAP_STREAMER_JETSON_MM_UNAVAILABLE_REASON)
set(_CVMMAP_STREAMER_JETSON_MM_AVAILABLE FALSE)
else()
set(_CVMMAP_STREAMER_JETSON_MM_UNAVAILABLE_REASON "Jetson Multimedia API dependencies")
set(_CVMMAP_STREAMER_JETSON_MM_AVAILABLE TRUE)
endif()
cvmmap_streamer_resolve_feature_mode(
CVMMAP_STREAMER_HAS_JETSON_MM_BOOL
CVMMAP_STREAMER_ENABLE_JETSON_MM
"${CVMMAP_STREAMER_ENABLE_JETSON_MM}"
${_CVMMAP_STREAMER_JETSON_MM_AVAILABLE}
"${_CVMMAP_STREAMER_JETSON_MM_UNAVAILABLE_REASON}")
if (CVMMAP_STREAMER_HAS_JETSON_MM_BOOL)
set(CVMMAP_STREAMER_HAS_JETSON_MM 1)
add_library(cvmmap_streamer_jetson_mmapi STATIC
${_CVMMAP_STREAMER_JETSON_MM_COMMON_SOURCES})
target_include_directories(cvmmap_streamer_jetson_mmapi
PUBLIC
"${_CVMMAP_STREAMER_JETSON_MM_INCLUDE_DIR}")
target_link_libraries(cvmmap_streamer_jetson_mmapi
PUBLIC
Threads::Threads
${CVMMAP_STREAMER_LIBV4L2_LIBRARY}
${CVMMAP_STREAMER_NVBUFSURFACE_LIBRARY})
else()
set(CVMMAP_STREAMER_HAS_JETSON_MM 0)
endif()
if (NOT TARGET cvmmap::client)
if (
EXISTS "${CVMMAP_LOCAL_ROOT}/core/include/cvmmap/client.hpp"
@@ -344,13 +430,17 @@ add_library(cvmmap_streamer_feature_flags INTERFACE)
target_compile_definitions(cvmmap_streamer_feature_flags
INTERFACE
CVMMAP_STREAMER_HAS_MCAP=${CVMMAP_STREAMER_HAS_MCAP}
CVMMAP_STREAMER_HAS_MCAP_DEPTH=${CVMMAP_STREAMER_HAS_MCAP_DEPTH})
CVMMAP_STREAMER_HAS_MCAP_DEPTH=${CVMMAP_STREAMER_HAS_MCAP_DEPTH}
CVMMAP_STREAMER_HAS_JETSON_MM=${CVMMAP_STREAMER_HAS_JETSON_MM})
add_library(cvmmap_streamer_record_support STATIC
src/encode/encoder_backend.cpp
src/encode/ffmpeg_encoder_backend.cpp
src/record/protobuf_descriptor.cpp
src/record/mp4_record_writer.cpp)
if (CVMMAP_STREAMER_HAS_JETSON_MM_BOOL)
target_sources(cvmmap_streamer_record_support PRIVATE src/encode/jetson_mm_encoder_backend.cpp)
endif()
target_include_directories(cvmmap_streamer_record_support
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/include"
@@ -369,6 +459,9 @@ endif()
if (TARGET PkgConfig::PROTOBUF_PKG)
target_link_libraries(cvmmap_streamer_record_support PUBLIC PkgConfig::PROTOBUF_PKG)
endif()
if (CVMMAP_STREAMER_HAS_JETSON_MM_BOOL)
target_link_libraries(cvmmap_streamer_record_support PUBLIC cvmmap_streamer_jetson_mmapi)
endif()
if (CVMMAP_STREAMER_HAS_MCAP)
add_library(cvmmap_streamer_mcap_runtime STATIC
@@ -465,7 +558,9 @@ endif()
target_link_libraries(cvmmap_streamer_common PUBLIC ${CVMMAP_STREAMER_LINK_DEPS})
function(cvmmap_streamer_apply_build_rpath target)
function(cvmmap_streamer_apply_runtime_rpath target)
set_target_properties(${target} PROPERTIES
INSTALL_RPATH "${CVMMAP_STREAMER_INSTALL_RPATH}")
if (CVMMAP_STREAMER_BUILD_RPATH)
set_target_properties(${target} PROPERTIES
BUILD_RPATH "${CVMMAP_STREAMER_BUILD_RPATH}")
@@ -484,7 +579,7 @@ function(add_cvmmap_binary target source)
set_target_properties(${target} PROPERTIES
OUTPUT_NAME "${target}"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
cvmmap_streamer_apply_build_rpath(${target})
cvmmap_streamer_apply_runtime_rpath(${target})
endfunction()
add_cvmmap_binary(cvmmap_streamer src/main_streamer.cpp)
@@ -522,7 +617,7 @@ if (CVMMAP_STREAMER_HAS_MCAP)
set_target_properties(mcap_reader_tester PROPERTIES
OUTPUT_NAME "mcap_reader_tester"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
cvmmap_streamer_apply_build_rpath(mcap_reader_tester)
cvmmap_streamer_apply_runtime_rpath(mcap_reader_tester)
add_executable(mcap_replay_tester src/testers/mcap_replay_tester.cpp)
target_include_directories(mcap_replay_tester
@@ -548,7 +643,7 @@ if (CVMMAP_STREAMER_HAS_MCAP)
set_target_properties(mcap_replay_tester PROPERTIES
OUTPUT_NAME "mcap_replay_tester"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
cvmmap_streamer_apply_build_rpath(mcap_replay_tester)
cvmmap_streamer_apply_runtime_rpath(mcap_replay_tester)
endif()
if (CVMMAP_STREAMER_HAS_MCAP_DEPTH)