jpegTegraEncoderCompress() crashes with a SEGV

I wrote the following function using the fd_to_jpeg_impl class.

However, when I call the compress() function, it crashes with a SEGV in:

0x0000007fb6531354 in jpegTegraEncoderCompress () from /usr/lib/aarch64-linux-gnu/tegra/libnvjpeg.so

Here are my class & function:

namespace
{


class fd_to_jpeg_impl
{
public:
                fd_to_jpeg_impl();
                ~fd_to_jpeg_impl();

    void        compress(int fd);
    void        save(std::string const & filename);

private:
    jpeg_compress_struct    f_cinfo = {};
    jpeg_error_mgr          f_jerr = {};
    std::vector<char>       f_buffer = {};
};


fd_to_jpeg_impl::fd_to_jpeg_impl()
{
    f_cinfo.err = jpeg_std_error(&f_jerr);

    jpeg_create_compress(&f_cinfo);
    jpeg_suppress_tables(&f_cinfo, TRUE);
}


fd_to_jpeg_impl::~fd_to_jpeg_impl()
{
    jpeg_destroy_compress(&f_cinfo);
}


void fd_to_jpeg_impl::compress(int fd)
{
    if(fd == -1)
    {
        std::cerr << "error: fd_to_jpeg expects a valid fd as input." << std::endl;
        return;
    }

    // allocate a buffer to save the compressed data
    //
    f_buffer.resize(3840 * 2160 * 3);

    unsigned char * out_buf(reinterpret_cast<unsigned char *>(f_buffer.data()));
    unsigned long out_buf_size(f_buffer.size());

    jpeg_mem_dest(&f_cinfo, &out_buf, &out_buf_size);

    if(out_buf != reinterpret_cast<unsigned char *>(f_buffer.data()))
    {
        free(reinterpret_cast<void *>(*out_buf));
        std::cerr << "error: the JPEG library reallocated our buffer." << std::endl;
        return;
    }

    f_cinfo.fd = fd;
    f_cinfo.IsVendorbuf = TRUE;
    f_cinfo.raw_data_in = TRUE;
    f_cinfo.in_color_space = JCS_YCbCr;
    jpeg_set_defaults(&f_cinfo);
    jpeg_set_quality(&f_cinfo, 75, TRUE); // 75 is a bit low, but we're just debugging with those
    jpeg_set_hardware_acceleration_parameters_enc(&f_cinfo, TRUE, out_buf_size, 0, 0);

    // TBD: useless? it's already set that way above
    //
    f_cinfo.in_color_space = JCS_YCbCr;

    jpeg_start_compress(&f_cinfo, 0);

    if(f_cinfo.err->msg_code)
    {
        char err_string[256];
        f_cinfo.err->format_message((j_common_ptr) &f_cinfo, err_string);
        std::cerr << "error:fd_to_jpeg: " << err_string << std::endl;
        return;
    }

    jpeg_write_raw_data(&f_cinfo, nullptr, 0);    // <-- crashes in this call
    jpeg_finish_compress(&f_cinfo);
}


void fd_to_jpeg_impl::save(std::string const & filename)
{
        ...code not reached...
}


void fd_to_jpeg(int fd, std::string const & filename)
{
    fd_to_jpeg_impl obj;
    obj.compress(fd);
    obj.save(filename);
}

Here is the beginning of the stack up to fd_to_jpeg():

Thread 1 "favorite-icon-g" received signal SIGSEGV, Segmentation fault.
0x0000007fb6531354 in jpegTegraEncoderCompress () from /usr/lib/aarch64-linux-gnu/tegra/libnvjpeg.so
(gdb) where
#0  0x0000007fb6531354 in jpegTegraEncoderCompress () at /usr/lib/aarch64-linux-gnu/tegra/libnvjpeg.so
#1  0x0000007fb64fb354 in jpeg_write_raw_data () at /usr/lib/aarch64-linux-gnu/tegra/libnvjpeg.so
#2  0x00000055555949f4 in (anonymous namespace)::fd_to_jpeg_impl::compress(int) (this=0x7fffffdf20, fd=1194)
    at /home/alexis/ve/virtual-entertainment/panel-ve/src/fd_to_jpeg.cpp:142
#3  0x0000005555594c10 in fd_to_jpeg(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (fd=1194, filename="f1000a.jpg") at /home/alexis/ve/virtual-entertainment/panel-ve/src/fd_to_jpeg.cpp:173

I’m wondering whether someone would know about the reason for that crash.

The class above uses the samples/common/classes/NvJpegEncoder.cpp code one to one (except for the name of the variables and the destination buffer).

Hi,
Please check if you can run successfully by calling NvJPEGEncoder::encodeFromFd(). You would need to call NvBufferCreate() to get the fd nd set to cinfo.fd.

I’m using NvJPEGEncoder::encodeFromFd(). My class is copy & paste of the encodeFromFd() function, except for the buffer and I added f_ in front of the variable members which makes it a lot easier to know these are such.

Also, I can’t use an NvBuffer along that function. It just expects one fd as a parameter. I have such from my frame which was just converted (I get NAL data which I decompress then convert and finally display on the screen). Displaying on the screen works perfectly with that same fd. So I thought that if the fd works with NvEGLImageFromFd(), it would work just find with the JPEG library extensions.

    f_egl_images[idx] = NvEGLImageFromFd(
                              display
                            , frame->get_fd());

Further, I have a JPEG decoder (similar the other way around) and that one works perfectly. It can load JPEG images as long as they are in 4:2:0 and RGB.

Hi,
Could you try to call NvBufferGetParams(fd) and see if you can get information about the buffer?

Okay, I realized that the NvBuffer I have was converted to RGB so I could just save the frame using a PPM image. Much easier and it doesn’t crash.

I think that the issue was that your code probably doesn’t check whether the 3 planes are properly defined and if one is a null pointer, it just tries to access data at that invalid address and crashes.

In any event, I’m good on my end. Thank you for your help.