[vlc-commits] [Git][videolan/vlc][master] 3 commits: video_filter: replace cv::imwrite with picture_t write
Steve Lhomme (@robUx4)
gitlab at videolan.org
Wed Jun 3 13:10:11 UTC 2026
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
51f2c043 by Brandon Li at 2026-06-03T11:27:21+00:00
video_filter: replace cv::imwrite with picture_t write
- - - - -
63077a1b by Brandon Li at 2026-06-03T11:27:21+00:00
contrib: compile opencv4 with function/data sections
- - - - -
e367fe5c by Brandon Li at 2026-06-03T11:27:21+00:00
buildsystem: enable dead code stripping at link time
- - - - -
6 changed files:
- configure.ac
- contrib/src/opencv4/rules.mak
- meson.build
- modules/video_filter/Makefile.am
- modules/video_filter/meson.build
- modules/video_filter/sam3.cpp
Changes:
=====================================
configure.ac
=====================================
@@ -492,6 +492,29 @@ case "${host_os}" in
;;
esac
+dnl
+dnl Drops unused symbols.
+dnl ELF linkers use --gc-sections, while Mach-O uses -dead_strip.
+dnl
+AC_MSG_CHECKING([for linker dead-code stripping flag])
+GC_SECTIONS_LDFLAGS=""
+VLC_SAVE_FLAGS
+AX_APPEND_FLAG([-Wl,--gc-sections], [LDFLAGS])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
+ [GC_SECTIONS_LDFLAGS="-Wl,--gc-sections"], [])
+VLC_RESTORE_FLAGS
+AS_IF([test -z "${GC_SECTIONS_LDFLAGS}"], [
+ VLC_SAVE_FLAGS
+ AX_APPEND_FLAG([-Wl,-dead_strip], [LDFLAGS])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
+ [GC_SECTIONS_LDFLAGS="-Wl,-dead_strip"], [])
+ VLC_RESTORE_FLAGS
+])
+AS_IF([test -n "${GC_SECTIONS_LDFLAGS}"],
+ [AC_MSG_RESULT([${GC_SECTIONS_LDFLAGS}])],
+ [AC_MSG_RESULT([none])])
+AC_SUBST([GC_SECTIONS_LDFLAGS])
+
dnl WinRT
AC_ARG_ENABLE([winstore_app],
AS_HELP_STRING([--enable-winstore-app],
=====================================
contrib/src/opencv4/rules.mak
=====================================
@@ -37,6 +37,7 @@ opencv4: opencv-$(OPENCV4_VERSION).tar.gz .sum-opencv4
# only enable necessary pkgs
OPENCV4_ENV =
+
OPENCV4_CONF := \
-DBUILD_LIST=core,imgproc,imgcodecs,objdetect \
-DOPENCV_GENERATE_PKGCONFIG=ON \
@@ -71,7 +72,10 @@ OPENCV4_CONF := \
-DBUILD_ZLIB=OFF \
-DBUILD_PNG=OFF \
-DBUILD_JPEG=OFF \
- -DBUILD_ITT=OFF
+ -DBUILD_ITT=OFF \
+ -DOPENCV_FORCE_FUNCTIONS_SECTIONS=ON
+# OpenCV's adds -ffunction-sections/-fdata-sections by default, but skips for static
+# iOS/Android builds. Force it on
# NEON mandatory on aarch64
ifneq ($(findstring aarch64,$(HOST)),)
=====================================
meson.build
=====================================
@@ -927,6 +927,15 @@ if cc.has_link_argument('-Wl,-Bsymbolic')
symbolic_linkargs += '-Wl,-Bsymbolic'
endif
+# Drops unused symbols.
+# ELF linkers use --gc-sections, while Mach-O uses -dead_strip.
+gc_sections_linkargs = []
+if cc.has_link_argument('-Wl,--gc-sections')
+ gc_sections_linkargs += '-Wl,--gc-sections'
+elif cc.has_link_argument('-Wl,-dead_strip')
+ gc_sections_linkargs += '-Wl,-dead_strip'
+endif
+
# Check for struct sockaddr_storage type
# Define it to `sockaddr` if missing
sockaddr_prefix = ['#include <sys/types.h>']
=====================================
modules/video_filter/Makefile.am
=====================================
@@ -127,7 +127,7 @@ video_filter_PLUGINS += \
libsam3_plugin_la_SOURCES = video_filter/sam3.cpp
libsam3_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(OPENCV4_CFLAGS)
libsam3_plugin_la_CXXFLAGS = $(AM_CXXFLAGS) -fexceptions
-libsam3_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(video_filterdir)'
+libsam3_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(GC_SECTIONS_LDFLAGS) -rpath '$(video_filterdir)'
libsam3_plugin_la_LIBADD = $(LIBM) $(OPENCV4_LIBS)
EXTRA_LTLIBRARIES += libsam3_plugin.la
video_filter_LTLIBRARIES += $(LTLIBsam3)
@@ -235,7 +235,7 @@ endif
libopencv_wrapper_plugin_la_SOURCES = video_filter/opencv_wrapper.cpp
libopencv_wrapper_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(OPENCV_CFLAGS)
libopencv_wrapper_plugin_la_LIBADD = $(OPENCV_LIBS)
-libopencv_wrapper_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(video_filter_RPATH)
+libopencv_wrapper_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(GC_SECTIONS_LDFLAGS) $(video_filter_RPATH)
video_filter_PLUGINS += $(LTLIBopencv_wrapper)
EXTRA_LTLIBRARIES += libopencv_wrapper_plugin.la
@@ -271,7 +271,7 @@ video_filter_PLUGINS += libblend_plugin.la
libopencv_example_plugin_la_SOURCES = video_filter/opencv_example.cpp video_filter/filter_event_info.h
libopencv_example_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(OPENCV_CFLAGS)
libopencv_example_plugin_la_LIBADD = $(OPENCV_LIBS)
-libopencv_example_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(video_filter_RPATH)
+libopencv_example_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(GC_SECTIONS_LDFLAGS) $(video_filter_RPATH)
video_filter_PLUGINS += $(LTLIBopencv_example)
EXTRA_LTLIBRARIES += libopencv_example_plugin.la
=====================================
modules/video_filter/meson.build
=====================================
@@ -419,6 +419,7 @@ vlc_modules += {
'name' : 'opencv_wrapper',
'sources' : files('opencv_wrapper.cpp'),
'dependencies' : [m_lib, opencv_dep],
+ 'link_args' : gc_sections_linkargs,
'enabled' : opencv_dep.found()
}
@@ -426,6 +427,7 @@ vlc_modules += {
'name' : 'opencv_example',
'sources' : files('opencv_example.cpp'),
'dependencies' : [m_lib, opencv_dep],
+ 'link_args' : gc_sections_linkargs,
'enabled' : opencv_dep.found()
}
@@ -441,6 +443,7 @@ if opencv_dep.found() and sam3_dep.found()
opencv_dep,
sam3_dep,
],
- 'cpp_args' : [ '-fexceptions' ]
+ 'cpp_args' : [ '-fexceptions' ],
+ 'link_args' : gc_sections_linkargs
}
endif
\ No newline at end of file
=====================================
modules/video_filter/sam3.cpp
=====================================
@@ -32,6 +32,7 @@
#include <vlc_plugin.h>
#include <vlc_filter.h>
#include <vlc_picture.h>
+#include <vlc_block.h>
#include <vlc_mouse.h>
#include <vlc_fs.h>
@@ -142,6 +143,61 @@ vlc_module_begin( )
N_ ( "Natural-language concept to segment" ) )
vlc_module_end( )
+/*****************************************************************************
+* WriteMatAsImage: Encodes a Mat and writes to disk
+*****************************************************************************/
+static bool WriteMatAsImage( filter_t* p_filter, const cv::Mat& mat_bgr,
+ const char* psz_path, vlc_fourcc_t i_codec )
+{
+ if ( mat_bgr.empty( ) || mat_bgr.type( ) != CV_8UC3 )
+ {
+ return false;
+ }
+
+ video_format_t fmt_in;
+ video_format_Init( &fmt_in, VLC_CODEC_BGR24 );
+ video_format_Setup( &fmt_in, VLC_CODEC_BGR24,
+ mat_bgr.cols, mat_bgr.rows,
+ mat_bgr.cols, mat_bgr.rows, 1, 1 );
+
+ picture_t* p_pic = picture_NewFromFormat( &fmt_in );
+ if ( !p_pic )
+ {
+ return false;
+ }
+
+ // copy planes
+ plane_t* p_plane = &p_pic->p[ 0 ];
+ const size_t i_row_bytes = static_cast<size_t>( mat_bgr.cols ) * 3;
+ for ( int y = 0; y < mat_bgr.rows; ++y )
+ {
+ memcpy( p_plane->p_pixels + y * p_plane->i_pitch,
+ mat_bgr.ptr( y ), i_row_bytes );
+ }
+
+ block_t* p_block = nullptr;
+ const int i_ret = picture_Export( VLC_OBJECT( p_filter ), &p_block, nullptr,
+ p_pic, i_codec, 0, 0, false );
+ picture_Release( p_pic );
+
+ if ( i_ret != VLC_SUCCESS || !p_block )
+ {
+ return false;
+ }
+
+ FILE* p_file = vlc_fopen( psz_path, "wb" );
+ bool b_ok = false;
+ if ( p_file )
+ {
+ const size_t i_written = fwrite( p_block->p_buffer, 1, p_block->i_buffer, p_file );
+ b_ok = ( i_written == p_block->i_buffer );
+ fclose( p_file );
+ }
+
+ block_Release( p_block );
+ return b_ok;
+}
+
/*****************************************************************************
* Export: Export a single mask to file
*****************************************************************************/
@@ -168,28 +224,27 @@ static void Export( filter_t* p_filter, const segmented_object_t& obj, const cv:
cv::resize( obj.mat_mask, mat_mask_scaled, mat_frame.size( ), 0, 0, cv::INTER_LINEAR );
cv::threshold( mat_mask_scaled, mat_mask_scaled, 128, 255, cv::THRESH_BINARY );
- // create file name
- std::string str_filename = std::string( p_sys->psz_export_path ) + "/mask_" +
+ // export the original frame as a 3-channel PNG
+ std::string frame_filename = std::string( p_sys->psz_export_path ) + "/frame_" +
psz_timestamp + "_id" + std::to_string( obj.i_id ) + ".png";
-
- // export mask onto Mat - optimized version
- std::vector<cv::Mat> vec_channels;
- cv::split( mat_frame, vec_channels );
- vec_channels.push_back( mat_mask_scaled );
- cv::Mat mat_export;
- cv::merge( vec_channels, mat_export );
-
- // write image
- if ( !cv::imwrite( str_filename, mat_export ) )
+ if ( !WriteMatAsImage( p_filter, mat_frame, frame_filename.c_str( ), VLC_CODEC_PNG ) )
{
- msg_Err( p_filter, "Failed to export mask to %s", str_filename.c_str( ) );
+ msg_Err( p_filter, "Failed to export frame to %s", frame_filename.c_str( ) );
return;
}
- msg_Info( p_filter, "Exported mask %d to %s", obj.i_id, str_filename.c_str( ) );
+ msg_Info( p_filter, "Exported frame %d to %s", obj.i_id, frame_filename.c_str( ) );
- // create file name
- std::string vis_filename = std::string( p_sys->psz_export_path ) + "/visualization_" +
- psz_timestamp + "_id" + std::to_string( obj.i_id ) + ".jpg";
+ // export the binary mask as a grayscale PNG
+ cv::Mat mat_mask_bgr;
+ cv::cvtColor( mat_mask_scaled, mat_mask_bgr, cv::COLOR_GRAY2BGR );
+ std::string mask_filename = std::string( p_sys->psz_export_path ) + "/mask_" +
+ psz_timestamp + "_id" + std::to_string( obj.i_id ) + ".png";
+ if ( !WriteMatAsImage( p_filter, mat_mask_bgr, mask_filename.c_str( ), VLC_CODEC_PNG ) )
+ {
+ msg_Err( p_filter, "Failed to export mask to %s", mask_filename.c_str( ) );
+ return;
+ }
+ msg_Info( p_filter, "Exported mask %d to %s", obj.i_id, mask_filename.c_str( ) );
// clone image, add mask overlay
cv::Mat mat_visualization = mat_frame.clone( );
@@ -215,8 +270,10 @@ static void Export( filter_t* p_filter, const segmented_object_t& obj, const cv:
}
cv::drawContours( mat_visualization, vec_scaled_contours, -1, obj.scalar_color, 2, cv::LINE_AA );
- // write image
- if ( !cv::imwrite( vis_filename, mat_visualization ) )
+ // export the visualization as JPEG
+ std::string vis_filename = std::string( p_sys->psz_export_path ) + "/visualization_" +
+ psz_timestamp + "_id" + std::to_string( obj.i_id ) + ".jpg";
+ if ( !WriteMatAsImage( p_filter, mat_visualization, vis_filename.c_str( ), VLC_CODEC_JPEG ) )
{
msg_Err( p_filter, "Failed to export visualization to %s", vis_filename.c_str( ) );
return;
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ca850d6979a333e8fe191532e46c078f4724facf...e367fe5c26b18dcd789a73061ec79680889b831c
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ca850d6979a333e8fe191532e46c078f4724facf...e367fe5c26b18dcd789a73061ec79680889b831c
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list