Hi all, I am an engineer working at Manything (https://manything.com). We develop software that allows users to view their security cameras over the Internet. Thomas has been working with us to develop this mbedTLS integration.
Thanks for your feedback on his patch; we have run some tests that I hope will answer some of your questions. We've not been able to produce all the detail you've requested, but hopefully what we have is a compelling case. With some advice, I hope we could produce any other evidence you need to support acceptance of the patch. This is our first contribution back to FFmpeg, so we welcome guidance on how to do the right things in the right way. First, a bit of context on our motivation. We write software that runs on IP cameras to connect them to our cloud service. We started off by using GnuTLS to secure our connections but there's very limited disk space on the cameras and the relatively large binary footprint caused some problems. Looking around for an alternative library we discovered mbedTLS, a project with a good open-source heritage, suitable license terms and a major commercial backer (ARM Holdings). We were easily able to make use of its integration with cURL but it wasn't yet supported by the FFmpeg project, so we found Thomas via the project's consulting page and embarked on the integration. mbedTLS is an excellent fit for our needs; I hope this is an indicator of its potential value to other FFmpeg users. Below you will find our method and results. We look forward to your feedback. Many thanks, Dave -- FFmpeg TLS libraries: disk and memory footprint comparison report Goal: Compare the memory usage and disk footprint of the new mbedTLS integration against the three existing platform-agnostic TLS libraries supported by FFmpeg. Approach summary (full detail in appendix A): - Build FFmpeg against four TLS libraries, measure output library sizes. - schannel (Windows) and securetransport (macOS) are excluded from the analysis because it would be very difficult to compare results fairly across different operating systems (and impossible on a Linux test rig). - Stream well-known free video file (Big Buck Bunny) to remote rtsps server in realtime, collect memory statistics with valgrind/massif. - Interrogate massif outputs to assess relative memory consumption of each library. Note: The project's actual devices are mostly ARM-based but we have found valgrind hard to run on ARM. The stats below have therefore been created on an x86_64 box to provide memory measurements easily and repeatably. Results summary (full detail in appendix B): - GnuTLS 3.4.17 - Peak ssl/tls/crypto-related memory allocation: 4.36MB - TLS library file size on disk, including dependencies: 5.5MB - LibreSSL 2.7.2 (libtls) - Results - Peak ssl/tls/crypto-related memory allocation: 115KB - TLS library file size on disk, including dependencies: 3.27MB - mbedTLS 2.8.0 - Results - Peak ssl/tls/crypto-related memory allocation: 40KB - TLS library file size on disk, including dependencies: 828KB - OpenSSL 1.0.2n - Results - Peak ssl/tls/crypto-related memory allocation: 151KB - TLS library file size on disk, including dependencies: 2.7MB All supporting data can be downloaded from https://assetcdn.manything.com/downloads/data/ffmpeg_tls_massif_data.tar.xz. Conclusion: For the task of outbound interleaved RTSPS streaming, mbedTLS uses about 35% of the memory of LibreSSL/libtls (its nearest competitor) with only 25% of the disk footprint. --- APPENDIX A: Test detail Test system: - Linux vagrant-ubuntu-trusty-64 3.13.0-87-generic #133-Ubuntu (VM) - Running in virtualbox on MacBook Pro (Retina, 13-inch, Early 2015) - Ubuntu EGLIBC 2.19-0ubuntu6.11 Test process: - Compile dependencies, with configuration flags listed, and install into custom prefix (referred to as ${DEPS_OUTDIR}) - Unless otherwise specified, steps are: configure --prefix=${DEPS_OUTDIR} (any extra flags specified above) make make install - Measure size of relevant libs e.g. ls -lh ${DEPS_OUTDIR}/lib/ | grep 'ssl\|crypto\|tls\|nettle\|hogweed\|gmp\|gpg\|gcrypt' - Compile ffmpeg against dependencies, with additional configuration flags listed above. configure --prefix=${DEPS_OUTDIR} --disable-stripping --disable-debug --enable-shared --disable-everything --enable-version3 --enable-parser=h264,hevc,aac --enable-decoder=h264,hevc,aac,pcm_alaw,pcm_mulaw --enable-protocol=tcp,udp,file,tls,tls_gnutls --enable-demuxer=rtsp --enable-muxer=rtsp,mp4,mpegts,pcm_alaw,pcm_mulaw --disable-ffplay --disable-ffprobe --disable-doc --disable-avdevice - Stream known free video file to remote rtsps server in realtime, wrapped in valgrind/massif valgrind --tool=massif --threshold=0.1 ${DEPS_OUTDIR}/bin/ffmpeg -re -i BigBuckBunny_320x180.mp4 -c:v copy -c:a copy -f rtsp -rtsp_transport tcp rtsps://USER:PASS@REMOTEHOST:443/STREAMNAME - Redact sensitive information (remote creds/url) from massif.out - Rename massif.out.NNNNN and process through ms_print: mv massif.out.NNNNN massif.out.LIBNAME ms_print --threshold=0.1 massif.out.LIBNAME > ms_print.massif.out.LIBNAME - Generate visualizations for each massif.out with massif-visualizer - Perform detailed memory analysis on each snapshot: - Filter the heap graph (ms_print.out) to include only top-level items.: grep -e '^->' -e '^---' -e '^\s\+[0-9n]\+ ' ms_print.massif.out.LIBNAME > ms_print.massif.out.LIBNAME.toplevelfilter - For each snapshot, sum values for crypto/tls libraries to get total crypto/tls heap usage for that snap. - Identify steady-state value from a snap near the middle of the run. - Identify peak value, if different from steady-state. --- APPENDIX B: Full results with library configurations - GnuTLS 3.4.17 - TLS library compile-time configuration configure --prefix=${DEPS_OUTDIR} --with-libz-prefix=${DEPS_OUTDIR} --enable-shared --without-p11-kit --with-included-libtasn1 --disable-doc make make install - Dependencies with configure flags: - zlib 1.2.11 (configure --prefix=${DEPS_OUTDIR}) - gmp 6.1.2 (configure --prefix=${DEPS_OUTDIR}) - nettle 3.1 (configure --prefix=${DEPS_OUTDIR} --enable-shared --disable-assembler --disable-openssl) - gpg-error 1.26 (configure --prefix=${DEPS_OUTDIR}) - gcrypt 1.7.5 (configure --prefix=${DEPS_OUTDIR} --with-libgpg-error-prefix=${DEPS_OUTDIR}) - Additional FFmpeg configure flags (main set below): --enable-gnutls --enable-protocol=tcp,udp,file,tls,tls_gnutls - Results - Key tls/crypto-related memory allocation from detailed snapshots: Peak: 4.36MB from snap #5 Steady-state: 4.1MB from snap #36 - Values for other snapshots, and detail for peak: #4: 3.6MB #5: 4.36MB 5 117,151,532 6,229,360 5,747,248 482,112 0 ->61.00% (3,800,000B) 0x6C75D95: _asn1_add_single_node (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->16.81% (1,047,104B) 0x5DEDB16: av_realloc_f (in /home/build/2.3.0-rtsps.gnutls.2/lib/libavutil.so.56.15.100) ->04.40% (274,341B) 0x6BBEC3D: _gnutls_fread_file (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->03.19% (198,992B) 0x6B8F3CD: _gnutls_base64_decode (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->02.30% (143,357B) 0x6C74517: _asn1_set_value (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->01.62% (100,729B) 0x5DEDA0B: av_malloc (in /home/build/2.3.0-rtsps.gnutls.2/lib/libavutil.so.56.15.100) ->01.44% (89,984B) 0x6C740BD: _asn1_add_static_node (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->00.47% (29,479B) 0x6C745A8: _asn1_set_value_lv (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->00.37% (22,953B) in 43 places, all below massif's threshold (00.10%) ->00.31% (19,376B) 0x6BFD92F: gnutls_x509_crt_init (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->00.20% (12,741B) 0x6B9E022: gnutls_realloc_fast (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->00.13% (8,192B) 0x6C033B5: gnutls_x509_crt_list_import2 (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) #6: 4.1MB [...] #36: 4.1MB 36 770,323,285 5,988,232 5,503,656 484,576 0 ->63.45% (3,799,240B) 0x6C75D95: _asn1_add_single_node (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->17.49% (1,047,104B) 0x5DEDB16: av_realloc_f (in /home/build/2.3.0-rtsps.gnutls.2/lib/libavutil.so.56.15.100) ->03.32% (198,992B) 0x6B8F3CD: _gnutls_base64_decode (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->02.39% (143,357B) 0x6C74517: _asn1_set_value (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->02.02% (121,133B) 0x5DEDA0B: av_malloc (in /home/build/2.3.0-rtsps.gnutls.2/lib/libavutil.so.56.15.100) ->01.50% (89,984B) 0x6C740BD: _asn1_add_static_node (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->00.49% (29,479B) 0x6C745A8: _asn1_set_value_lv (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->00.44% (26,481B) in 67 places, all below massif's threshold (00.10%) ->00.37% (22,414B) 0x6B9E022: gnutls_realloc_fast (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->00.32% (19,376B) 0x6BFD92F: gnutls_x509_crt_init (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) ->00.10% (6,096B) 0x6C0A67E: gnutls_x509_trust_list_init (in /home/build/2.3.0-rtsps.gnutls.2/lib/libgnutls.so.30.7.0) #55: 4.1MB - File size on disk, including dependencies: 5.5MB -rwxr-xr-x 1 build build 1.4M Apr 27 10:36 libgcrypt.so.20.1.5 -rwxr-xr-x 1 build build 675K Apr 27 10:34 libgmp.so.10.3.2 -rwxr-xr-x 1 build build 1.7M Apr 27 10:41 libgnutls.so.30.7.0 -rwxr-xr-x 1 build build 195K Apr 27 10:41 libgnutlsxx.so.28.1.0 -rwxr-xr-x 1 build build 108K Apr 27 10:35 libgpg-error.so.0.21.0 -rw-r--r-- 1 build build 625K Apr 27 10:37 libhogweed.so.4.0 -rw-r--r-- 1 build build 757K Apr 27 10:37 libnettle.so.6.0 - LibreSSL 2.7.2 - TLS library compile-time configuration configure --prefix=${DEPS_OUTDIR} make make install - Dependencies with configurations (if any): - zlib 1.2.11 (configure --prefix=${DEPS_OUTDIR}) - Additional FFmpeg configure flags: --enable-libtls --enable-protocol=tcp,udp,file,tls,tls_openssl - Results - Key tls/crypto-related memory allocations from detailed snapshots: Peak / steady-state: 115KB from snap #40 - Values for other snapshots, and detail for peak: #2: <1KB #8: 115KB [...] #40: 115KB 40 720,412,615 1,374,584 1,323,570 51,014 0 ->76.18% (1,047,104B) 0x5DEDB16: av_realloc_f (in /home/build/2.3.0-rtsps.libtls.2/lib/libavutil.so.56.15.100) ->09.87% (135,655B) 0x5DEDA0B: av_malloc (in /home/build/2.3.0-rtsps.libtls.2/lib/libavutil.so.56.15.100) ->03.11% (42,792B) 0x7C72EDF: lh_insert (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->01.31% (17,951B) in 105 places, all below massif's threshold (00.10%) ->01.22% (16,712B) 0x78D43E5: ssl3_setup_read_buffer (in /home/build/2.3.0-rtsps.libtls.2/lib/libssl.so.45.0.1) ->01.20% (16,560B) 0x78D4533: ssl3_setup_write_buffer (in /home/build/2.3.0-rtsps.libtls.2/lib/libssl.so.45.0.1) ->01.04% (14,264B) 0x7CE1E17: reallocarray (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->00.46% (6,288B) 0x7C7AA22: OBJ_NAME_add (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->00.44% (6,010B) 0x6B4E4FD: tls_conninfo_cert_pem (in /home/build/2.3.0-rtsps.libtls.2/lib/libtls.so.17.0.1) ->00.35% (4,744B) 0x400BAF2: _dl_new_object (dl-object.c:75) ->00.23% (3,219B) 0x7BC1CFE: asn1_enc_save (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->00.17% (2,400B) 0x7BA5BBA: ASN1_OBJECT_new (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->00.17% (2,388B) 0x7CE1E6F: recallocarray (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->00.17% (2,328B) 0x7BBE5CD: asn1_item_ex_combine_new (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->00.15% (2,090B) 0x7BA14E3: c2i_ASN1_BIT_STRING (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->00.12% (1,656B) 0x7BADAC6: ASN1_STRING_type_new (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) ->00.10% (1,409B) 0x7BAD95F: ASN1_STRING_set (in /home/build/2.3.0-rtsps.libtls.2/lib/libcrypto.so.43.0.1) #58: 115KB #68: 115KB #78: 115KB - File size on disk, including dependencies: 3.27MB -rw-r--r-- 1 build build 2.7M Apr 27 12:31 libcrypto.so.43.0.1 -rw-r--r-- 1 build build 475K Apr 27 12:31 libssl.so.45.0.1 -rw-r--r-- 1 build build 96K Apr 27 12:31 libtls.so.17.0.1 - mbedTLS 2.8.0 - TLS library compile-time configuration cmake -DUSE_SHARED_MBEDTLS_LIBRARY=On -DCMAKE_INSTALL_PREFIX=${DEPS_OUTDIR} . sed -i "s|DESTDIR=/usr/local|DESTDIR=${DEPS_OUTDIR}|g" ${ROOTDIR}/deps/${MANUFACTURER}/${PLATFORM}/work/mbedtls/Makefile make install ${DEPS_OUTDIR} - Dependencies with configurations: - zlib 1.2.11 (configure --prefix=${DEPS_OUTDIR}) - Additional FFmpeg configure flags: --enable-mbedtls --enable-protocol=tcp,udp,file,tls,tls_mbedtls - Results - Key tls/crypto-related memory allocation from detailed snapshots: Peak / Steady-state: 40KB from snap #32 - Values for other snapshots, and detail for peak: #2: 40KB #17: 40KB #24: 40KB #32: 40KB 32 4,735,121,659 1,238,712 1,228,242 10,470 0 ->84.53% (1,047,104B) 0x5DEEB16: av_realloc_f (in /home/build/2.3.0-rtsps.1/lib/libavutil.so.56.15.100) ->10.20% (126,329B) 0x5DEEA0B: av_malloc (in /home/build/2.3.0-rtsps.1/lib/libavutil.so.56.15.100) ->01.35% (16,717B) 0x6B68FE3: mbedtls_ssl_setup (in /home/build/2.3.0-rtsps.1/lib/libmbedtls.so.2.8.0) ->01.35% (16,717B) 0x6B69012: mbedtls_ssl_setup (in /home/build/2.3.0-rtsps.1/lib/libmbedtls.so.2.8.0) ->00.76% (9,364B) in 48 places, all below massif's threshold (00.10%) ->00.38% (4,744B) 0x400BAF2: _dl_new_object (dl-object.c:75) ->00.35% (4,315B) 0x78DB3B1: x509_crt_parse_der_core (in /home/build/2.3.0-rtsps.1/lib/libmbedx509.so.2.8.0) ->00.13% (1,608B) 0x7AFF1DE: mbedtls_mpi_grow (in /home/build/2.3.0-rtsps.1/lib/libmbedcrypto.so.2.8.0) ->00.11% (1,344B) 0x78D7430: mbedtls_x509_get_name (in /home/build/2.3.0-rtsps.1/lib/libmbedx509.so.2.8.0) #36: 40KB #45: 40KB - File size on disk, including dependencies: 828KB -rwxr-xr-x 1 build build 479K Apr 25 08:27 libmbedcrypto.so.2.8.0 -rwxr-xr-x 1 build build 240K Apr 25 08:27 libmbedtls.so.2.8.0 -rwxr-xr-x 1 build build 109K Apr 25 08:27 libmbedx509.so.2.8.0 - OpenSSL 1.0.2n - TLS library compile-time configuration ./Configure linux-generic32 shared --prefix=${DEPS_OUTDIR} --openssldir=${DEPS_OUTDIR}/openssl make make install - Dependencies with configurations: - zlib 1.2.11 (configure --prefix=${DEPS_OUTDIR}) - Additional FFmpeg configure flags: --enable-openssl --enable-protocol=tcp,udp,file,tls,tls_openssl - Results - Key tls/crypto-related memory allocation from detailed snapshots: Peak / Steady-state: 151KB from snap #30 - Values for other snapshots, and detail for peak: #1: 82KB #8: 151KB [...] #30: 151KB 30 3,264,891,835 1,405,992 1,342,597 63,395 0 ->74.47% (1,047,104B) 0x5DEDB16: av_realloc_f (in /home/build/2.3.0-rtsps.2/lib/libavutil.so.56.15.100) ->09.57% (134,567B) 0x6E1B036: CRYPTO_malloc (in /home/build/2.3.0-rtsps.2/lib/libcrypto.so.1.0.0) ->09.31% (130,917B) 0x5DEDA0B: av_malloc (in /home/build/2.3.0-rtsps.2/lib/libavutil.so.56.15.100) ->01.39% (19,584B) 0x6E1B127: CRYPTO_realloc (in /home/build/2.3.0-rtsps.2/lib/libcrypto.so.1.0.0) ->00.40% (5,681B) in 30 places, all below massif's threshold (00.10%) ->00.34% (4,744B) 0x400BAF2: _dl_new_object (dl-object.c:75) #51: 151KB - File size on disk, including dependencies: 2.7MB -r-xr-xr-x 1 build build 2.2M Apr 25 16:00 libcrypto.so.1.0.0 -r-xr-xr-x 1 build build 506K Apr 25 16:00 libssl.so.1.0.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel