kornelski / mozjpeg-sys

Rust bindings for mozjpeg
https://lib.rs/crates/mozjpeg-sys
Other
33 stars 17 forks source link

Which dll/lib file is it linking to? / How to link to libjpeg-turbo instead? #6

Open Boscop opened 6 years ago

Boscop commented 6 years ago

This crate links to "jpeg" but where is this coming from? It builds successfully on Win 8.1 and the reencode example works even though I didn't download a jpeg.dll and didn't derive a .lib file from it.

The reason I'm asking is because I want to use libjpeg-turbo. I downloaded libjpeg-turbo-1.5.90-vc64.exe from here and installed it, now I have jpeg62.dll and turbojpeg.dll. Now I want to derive the .lib file from turbojpeg.dll and rename it to jpeg.lib and link to that, with mozjpeg-sys, how can I do that, if it's linking to some other jpeg lib by default?

(My use case is, I want to decode MJPEG frames coming from a webcam at 30 FPS to send them to the GPU for post-processing with glium. The jpeg-decoder crate uses too much CPU and only reaches 2 FPS in debug mode..)

kornelski commented 6 years ago

The links attribute is intended to mark that it conflicts with crates linking to the jpeg library, and this attribute doesn't do anything apart from that.

In the current implementation there is no dynamic linking, and it doesn't support anything except its own bundled static version of MozJPEG.

In any case, in this crate, I only intend to support MozJPEG, and not plain libjpeg-turbo.

Boscop commented 6 years ago

Ok, and is MozJPEG suitable for real-time 30 FPS MJPEG decoding?

kornelski commented 6 years ago

If it's not fast enough, you can disable mozjpeg-specific optimizations:

  ffi::jpeg_c_set_bool_param(cinfo, J_BOOLEAN_PARAM::JBOOLEAN_OPTIMIZE_SCANS, false)
  ffi::jpeg_c_set_bool_param(cinfo, J_BOOLEAN_PARAM::JBOOLEAN_USE_SCANS_IN_TRELLIS, false);
Boscop commented 6 years ago

Thanks!

Btw, how would decoding MJPEG frames differ from the reencode::decode() function (other than using jpeg_mem_src instead of jpeg_stdio_src)?

I guess I shouldn't call jpeg_read_header? Should I just call jpeg_std_error, jpeg_create_decompress once during setup and then jpeg_start_decompress and jpeg_read_scanlines for every frame, and then jpeg_finish_decompress and jpeg_destroy_decompress when exiting? I want to avoid re-doing stuff that doesn't have to be re-done for every frame.


Btw, this is my current code using escapi and the jpeg-decoder crate with glium:

const CAM_WIDTH: u32 = 1920;
const CAM_HEIGHT: u32 = 1080;
const CAM_FRAME_SIZE: usize = (CAM_WIDTH * CAM_HEIGHT) as _;

pub struct CamRenderer<'a> {
    cam: Capture,
    cam_frame: Box<[u32; CAM_FRAME_SIZE]>,
    cam_tex: texture::SrgbTexture2d,
    vertex_buffer: VertexBuffer<Vertex>,
    index_buffer: index::IndexBuffer<u16>,
    program: Program,
    params: DrawParameters<'a>,
    cam_name: &'a str,
    camera_count: u32,
}

impl<'a> CamRenderer<'a> {
    pub fn process<T: Surface>(&mut self, target: &mut T, state: &VjUiState) -> Result<(), i32> {
        if self.cam.is_capture_done() {
            use jpeg_decoder::*;
            let data = unsafe { slice::from_raw_parts(self.cam_frame.as_ptr() as *const u8, CAM_FRAME_SIZE * 4) };
            let mut decoder = Decoder::new(data);
            let decoded = decoder.decode().unwrap();
            self.cam.do_capture();
            self.cam_tex.main_level().write(Rect {
                    left: 0,
                    bottom: 0,
                    width: CAM_WIDTH as u32,
                    height: CAM_HEIGHT as u32
                }, texture::RawImage2d {
                    data: Cow::Owned(decoded),
                    width: CAM_WIDTH as u32,
                    height: CAM_HEIGHT as u32,
                    format: texture::ClientFormat::U8U8U8
                }
            );
// ... 
kornelski commented 6 years ago

Sorry, I don't know details of MJPEG. But the API is 1:1 libjpeg, so if you find any C example, it will be easy to translate.

Boscop commented 6 years ago

So it supports images that don't have a huffman table? It was necessary to add this to the jpeg-decoder crate to support MJPEG: https://github.com/kaksmet/jpeg-decoder/issues/76#issuecomment-325217490

kornelski commented 6 years ago

This implementation is based on libjpeg. Check what libjpeg does in this case.

Boscop commented 6 years ago

Thanks, I got it working :) Btw, is there a way to build the bundled static version of MozJPEG in release mode when I'm building my crate in debug mode?