$ cat /etc/nv_tegra_release
# R35 (release), REVISION: 5.0, GCID: 35550185, BOARD: t186ref, EABI: aarch64, DATE: Tue Feb 20 04:46:31 UTC 2024
$ md5sum libnvjpeg.so
fff1701242bf2bfd66613f3f17f43d2d libnvjpeg.so
We encounter SIGSEGV from encodeToBuffer() seldomly in our application. Unfortunately we can’t reproduce this with sample or test programs but have encountered this tens of times. We can reproduce this quite reliably but may take hours with our application during which thousands if not tens of thousands jpeg’s are encoded and decoded. We use encodeToBuffer() and decodeToBuffer() because those fit better in our image processing pipeline but have considered switching to encodeFromFd() and decodeFromFd().
We have ruled out almost certainly or checked:
-
Concurrency issues. We do use two
NvJPEGEncoderand twoNvJPEGDecoderinstances but always use one instance from one thread. Tested and this occurs also with just one instance of both. We have had concurrency issues before but they are fixed and the backtrace is different in those cases. -
Dynamic resolution. We discovered this undocumented feature from our own testing and these forums. We create a new instance for different resolutions. But keep alive just two instances. We have had these issues before and the backtrace is different in those cases.
-
Our application modifying the data being decoded mid decoding. Also extremely unlikely the
SIGSEGVwould happen always in exactly same location. -
JPEG quality is always 80 in our application
-
Corrupted JPEG. We check the JPEG headers before trying to decode. We have also checked the jpeg files for which the
SIGSEGVhappens. -
Weird resolutions. We do encode some non multiple of 16 resolutions but all resolutions we decode are multiples of 16. Also, this occurs with multiple resolutions
-
JPEG format. We always use
V4L2_PIX_FMT_YUV420M
But the SIGSEGV seems to happen always in same location and we have been able to mitigate and avoid this by modifying NvJpegDecoder.cpp with better error handling.
Backtrace:
#14
#15 \__memcpy_generic () at ../sysdeps/aarch64/multiarch/../memcpy.S:182
#16 0x0000ffff74ada0f4 in jpeg_read_raw_data () from /usr/lib/aarch64-linux-gnu/tegra/libnvjpeg.so
#17 0x0000aaaaea6f8a6c in NvJPEGDecoder::decodeDirect (this=this@entry=0xfffe14db3c60, out_buf=out_buf@entry=0xfffe14db52c0, pixel_format=pixel_format@entry=842091865) at /rootfs_arm64/usr/src/jetson_multimedia_api/samples/common/classes/NvJpegDecoder.cpp:418
#18 0x0000aaaaea6f9cd4 in NvJPEGDecoder::decodeToBuffer (this=0xfffe14db3c60, buffer=buffer@entry=0xfffe29fd5d70, in_buf=0xffff2105aa40 “\\377\\330\\377”, <incomplete sequence \\333>, in_buf_size=1512914, pixfmt=pixfmt@entry=0xfffe29fd5d6c,
width=width@entry=0xfffdb951cd0c, height=height@entry=0xfffdb951cd08) at /rootfs_arm64/usr/src/jetson_multimedia_api/samples/common/classes/NvJpegDecoder.cpp:243
Registers:
x[0]: 0xfffe2811fd10
x[1]: 0x0
x[2]: 0x7f0
x[3]: 0xfffe2811fd10
x[4]: 0x7f0
x[5]: 0xfffe28120500
x[6]: 0x800
x[7]: 0xc8c5cac2c6c6c5c3
x[8]: 0xc6c4c3bbbcc3c4c5
x[9]: 0xc3c7c7c3c2c5c4c1
x[10]: 0xc5c5c8c2c3c0c6c8
x[11]: 0xb2d8c9c2c4c6c8c6
x[12]: 0xc6c4c3bbbcc3c4c5
x[13]: 0xc3c7c7c3c2c5c4c1
x[14]: 0x0
x[15]: 0xc5c9c0c5c5c8c1ca
x[16]: 0xffff9f2c4000
x[17]: 0xffff95346e10
x[18]: 0xfffe497d4788
x[19]: 0xfffe29927578
x[20]: 0xfffe497d45a8
x[21]: 0x10
x[22]: 0xffff9f2c3000
x[23]: 0x8
x[24]: 0x40
x[25]: 0x7f0
x[26]: 0x80
x[27]: 0x0
x[28]: 0xfffe497d4910
x[29]: 0xfffe497d44f0
x[30]: 0xffff9f2820f4
Callstack:
Addr: 0xffff95346f28 Symbol: File: /lib/aarch64-linux-gnu/libc.so.6:-1
When SIGSEGV occurs cinfo.jpegTegraMgr->buff one or multiple buffers are null
(gdb) p cinfo
$6 = {err = 0xfffe3c0bdae0, mem = 0xfffe3c001020, progress = 0x0, jpegTegraMgr = 0xfffe3c0038c8, client_data = 0x0, is_decompressor = 1, tegra_acceleration = 1, mjpeg_decode = 1, buffer_in_use = 0, initWidth = 0, nvbufsurfptr = 0x0, initHeight = 0, initBitstreamBuffer = 0,
inputBuffSize = 12582912, outputBuffSize = 0, rgb565 = 0, IsVendorbuf = 0, pVendor_buf = 0x0, Vendorbuf_Size = 64, global_state = 202, fd = -1, bMeasure_ImageProcessTime = 0, src = 0xfffe3c0bdce0, image_width = 512, image_height = 512, num_components = 3,
jpeg_color_space = JCS_YCbCr, out_color_space = JCS_YCbCr, scale_num = 8, scale_denom = 8, output_gamma = 1, buffered_image = 0, raw_data_out = 1, dct_method = JDCT_IFAST, do_fancy_upsampling = 0, do_block_smoothing = 0, quantize_colors = 0, dither_mode = JDITHER_FS,
two_pass_quantize = 1, desired_number_of_colors = 256, enable_1pass_quant = 0, enable_external_quant = 0, enable_2pass_quant = 0, output_width = 512, output_height = 512, out_color_components = 3, output_components = 3, rec_outbuf_height = 1, actual_number_of_colors = 0,
colormap = 0x0, output_scanline = 0, input_scan_number = 1, input_iMCU_row = 0, output_scan_number = 0, output_iMCU_row = 0, coef_bits = 0x0, quant_tbl_ptrs = {0xfffe3c0bdd18, 0xfffe3c0bdda0, 0x0, 0x0}, dc_huff_tbl_ptrs = {0xfffe3c0bde28, 0xfffe3c0be058, 0x0, 0x0},
ac_huff_tbl_ptrs = {0xfffe3c0bdf40, 0xfffe3c0be170, 0x0, 0x0}, data_precision = 8, comp_info = 0xfffe3cd157e8, is_baseline = 1, progressive_mode = 0, arith_code = 0, arith_dc_L = ‘\\000’ <repeats 15 times>, arith_dc_U = ‘\\001’ <repeats 16 times>,
arith_ac_K = ‘\\005’ <repeats 16 times>, restart_interval = 0, saw_JFIF_marker = 0, JFIF_major_version = 1 ‘\\001’, JFIF_minor_version = 1 ‘\\001’, density_unit = 0 ‘\\000’, X_density = 1, Y_density = 1, saw_Adobe_marker = 0, Adobe_transform = 0 ‘\\000’, CCIR601_sampling = 0,
marker_list = 0xfffe3c00fc60, max_h_samp_factor = 2, max_v_samp_factor = 2, min_DCT_h_scaled_size = 8, min_DCT_v_scaled_size = 8, total_iMCU_rows = 32, sample_range_limit = 0x0, comps_in_scan = 3, cur_comp_info = {0xfffe3cd157e8, 0xfffe3cd15848, 0xfffe3cd158a8, 0x0},
MCUs_per_row = 0, MCU_rows_in_scan = 0, blocks_in_MCU = 0, MCU_membership = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Ss = 0, Se = 63, Ah = 0, Al = 0, block_size = 8, natural_order = 0xffffa48c73e8 <jpeg_natural_order>, lim_Se = 63, unread_marker = 0, b_frametodecode = 0,
b_surface_alloc_done = 1, tegra_surf = 0x0, input_frame_buf = 0xfffe3c1157e8 “\\377\\330\\377”, <incomplete sequence \\333>, pixel_row_cnt = 16, u_pixel_row_cnt = 1, v_pixel_row_cnt = 0, hw_error_status = 0, master = 0x0, main = 0x0, coef = 0x0, post = 0x0,
inputctl = 0xfffe3c0bdcb0, marker = 0xfffe3c0bdba8, entropy = 0x0, idct = 0x0, upsample = 0x0, cconvert = 0x0, cquantize = 0x0}
(gdb) print cinfo.jpegTegraMgr->buff\[0\]
$27 = (unsigned char \*) 0xffff5414c000 “\\361\\360\\356\\355\\355\\355\\356\\356\\357\\356\\355\\355\\355\\355\\355\\355\\360\\357\\357\\356\\356\\357\\357\\360\\361\\360\\357\\357\\356\\356\\356\\356\\360\\360\\360\\357\\357\\356\\356\\356\\355\\356\\356\\357\\360\\360\\361\\361\\356\\356\\357\\360\\360\\360\\357\\357\\360\\357\\356\\355\\355\\355\\356\\357\\356\\357\\357\\360\\357\\356\\355\\354\\357\\357\\357\\357\\357\\356\\355\\354\\357\\357\\357\\357\\357\\356\\355\\354\\356\\356\\356\\356\\356\\357\\357\\357\\357\\357\\356\\356\\356\\356\\357\\357\\356\\356\\357\\355\\354\\354\\355\\356\\355\\355\\355\\355\\355\\355\\355\\355\\355\\356\\357\\357\\360\\360\\360\\360\\360\\357\\357\\356\\356\\357\\357\\360\\361\\360\\357\\355\\354\\355\\355\\356\\355\\356\\357\\357\\360\\360\\360\\357\\357\\357\\357\\357\\357\\357\\357\\357\\356\\356\\356\\355\\355\\355\\355\\355\\357\\357\\357\\356\\356\\356\\356\\356\\357\\357\\356\\356\\356\\357\\360\\360\\357\\357\\356\\356\\356\\356\\357\\357\\357\\357\\357\\356\\356\\356\\356”, <incomplete sequence \\356>…
(gdb) print cinfo.jpegTegraMgr->buff\[1\]
$28 = (unsigned char \*) 0x0
(gdb) print cinfo.jpegTegraMgr->buff\[2\]
$29 = (unsigned char \*) 0x0
When setting break point as close as possible when sigsegv does not happen. We did this by breaking when u_pixel_row_cnt changes from 0 to 1
(gdb) p cinfo
$31 = {err = 0xfffe4c0d42b0, mem = 0xfffe4c00fdb0, progress = 0x0, jpegTegraMgr = 0xfffe4c012b98, client_data = 0x0,
is_decompressor = 1, tegra_acceleration = 1, mjpeg_decode = 1, buffer_in_use = 0, initWidth = 0, nvbufsurfptr = 0x0,
initHeight = 0, initBitstreamBuffer = 0, inputBuffSize = 12582912, outputBuffSize = 0, rgb565 = 0, IsVendorbuf = 0,
pVendor_buf = 0x0, Vendorbuf_Size = 64, global_state = 202, fd = -1, bMeasure_ImageProcessTime = 0, src = 0xfffe4c001c70,
image_width = 4064, image_height = 3040, num_components = 3, jpeg_color_space = JCS_YCbCr, out_color_space = JCS_YCbCr,
scale_num = 8, scale_denom = 8, output_gamma = 1, buffered_image = 0, raw_data_out = 1, dct_method = JDCT_IFAST,
do_fancy_upsampling = 0, do_block_smoothing = 0, quantize_colors = 0, dither_mode = JDITHER_FS, two_pass_quantize = 1,
desired_number_of_colors = 256, enable_1pass_quant = 0, enable_external_quant = 0, enable_2pass_quant = 0, output_width = 4064,
output_height = 3040, out_color_components = 3, output_components = 3, rec_outbuf_height = 1, actual_number_of_colors = 0,
colormap = 0x0, output_scanline = 0, input_scan_number = 1, input_iMCU_row = 0, output_scan_number = 0, output_iMCU_row = 0,
coef_bits = 0x0, quant_tbl_ptrs = {0xfffe4c001ca8, 0xfffe4c001d30, 0x0, 0x0}, dc_huff_tbl_ptrs = {0xfffe4c001db8, 0xfffe4c001fe8,
0x0, 0x0}, ac_huff_tbl_ptrs = {0xfffe4c001ed0, 0xfffe4c002100, 0x0, 0x0}, data_precision = 8, comp_info = 0xfffe4ccd54d8,
is_baseline = 1, progressive_mode = 0, arith_code = 0, arith_dc_L = ‘\\000’ <repeats 15 times>,
arith_dc_U = ‘\\001’ <repeats 16 times>, arith_ac_K = ‘\\005’ <repeats 16 times>, restart_interval = 0, saw_JFIF_marker = 0,
JFIF_major_version = 1 ‘\\001’, JFIF_minor_version = 1 ‘\\001’, density_unit = 0 ‘\\000’, X_density = 1, Y_density = 1,
saw_Adobe_marker = 0, Adobe_transform = 0 ‘\\000’, CCIR601_sampling = 0, marker_list = 0xfffe4c0c18e0, max_h_samp_factor = 2,
max_v_samp_factor = 2, min_DCT_h_scaled_size = 8, min_DCT_v_scaled_size = 8, total_iMCU_rows = 190, sample_range_limit = 0x0,
comps_in_scan = 3, cur_comp_info = {0xfffe4ccd54d8, 0xfffe4ccd5538, 0xfffe4ccd5598, 0x0}, MCUs_per_row = 0, MCU_rows_in_scan = 0,
blocks_in_MCU = 0, MCU_membership = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Ss = 0, Se = 63, Ah = 0, Al = 0, block_size = 8,
natural_order = 0xffffb98bd3e8 <jpeg_natural_order>, lim_Se = 63, unread_marker = 0, b_frametodecode = 0, b_surface_alloc_done = 1,
tegra_surf = 0x0, input_frame_buf = 0xfffe4c0d54d8 “\\377\\330\\377”, <incomplete sequence \\333>, pixel_row_cnt = 16,
u_pixel_row_cnt = 1, v_pixel_row_cnt = 0, hw_error_status = 0, master = 0x0, main = 0x0, coef = 0x0, post = 0x0,
inputctl = 0xfffe4c001c40, marker = 0xfffe4c001b38, entropy = 0x0, idct = 0x0, upsample = 0x0, cconvert = 0x0, cquantize = 0x0}
(gdb) print cinfo.jpegTegraMgr->buff\[0\]
$24 = (unsigned char \*) 0xfffe3883b000 “\_bb^ZYYX\[\\\_djr{\\201\\202\\211\\213\\223\\223\\236\\240\\245\\246\\251\\251\\247\\245\\245\\242\\235\\236\\233\\230\\225\\221\\214\\213\\214\\210\\206{tupjlfebafmqqt}\\200\\212\\212\\227\\232\\237\\242\\245\\252\\256\\263\\270\\273\\273\\271\\277\\301\\275\\273\\274\\274\\272\\275\\273\\267\\261\\260\\257\\251\\242\\225\\222\\214\\205\\201|riigdbbcdecedaafgedegjmrw{\\202\\212\\215\\221\\231\\237\\242\\246\\243\\253\\253\\262\\264\\256\\257\\260\\252\\247\\254\\253\\262\\255\\260\\260\\257\\252\\245\\242\\234\\223\\214\\211\\215\\200\\200vwnloqpuqxu{{yyyz{{zxxurrpkhhffggghlqqouwruyu”…
(gdb) print cinfo.jpegTegraMgr->buff\[1\]
$25 = (unsigned char \*) 0xffff181f9000 ‘\\200’ <repeats 200 times>…
(gdb) print cinfo.jpegTegraMgr->buff\[2\]
$26 = (unsigned char \*) 0xffff184f9000 ‘\\200’ <repeats 200 times>…
Thus we have been able to avoid SIGSEGV by checking if any of these buffers are null. And if so, creating a new decoder instance and retrying with same jpeg data seems to work.
@@ -222,6 +222,13 @@ NvJPEGDecoder::decodeToBuffer(NvBuffer ** buffer, unsigned char * in_buf,
cinfo.raw_data_out = TRUE;
jpeg_start_decompress (&cinfo);
+ if (!cinfo.jpegTegraMgr->buff[0]
+ || !cinfo.jpegTegraMgr->buff[1]
+ || !cinfo.jpegTegraMgr->buff[2])
+ {
+ return -1;
+ }
+
/* For some widths jpeglib requires more horizontal padding than I420
* provides. In those cases we need to decode into separate buffers and then
* copy over the data into our final picture buffer, otherwise jpeglib might
Is this known issue or fixed already in future releases? Or can you look into this with this information without us being able to provide sample program?