Skip to content

Naive GigE implementation#198

Draft
WhiteBlackGoose wants to merge 69 commits into
cameleon-rs:mainfrom
WhiteBlackGoose:gige
Draft

Naive GigE implementation#198
WhiteBlackGoose wants to merge 69 commits into
cameleon-rs:mainfrom
WhiteBlackGoose:gige

Conversation

@WhiteBlackGoose

@WhiteBlackGoose WhiteBlackGoose commented Nov 20, 2024

Copy link
Copy Markdown

Notes

  • It is only a partial implementation of GigE. Actually, a tiny bit of it, because only the following features are supported:
    • Single link mode
    • Single interface mode
    • One streaming channel
    • Image as payload
    • No H264 or multi-zone support
    • No request of the lost packets

It is however enough for the camera I need, and maybe I'll extend it if I get another camera which needs something beyond that.

  • The purpose of this PR is to share my work, in case someone's use case is exactly the same as mine (simple GigE cameras)

  • This PR is based on Y-Nak's work (and in fact, by far most of the work belongs to this person, I just finished the streaming part for my use case)

  • I didn't name my commits properly because if I'm actually to finish this PR so we could merge it, I'd imagine I'd need to squash and rewrite them many times because I expect quite a fair bit of feedback/change requests from the maintainer

  • GigE Example App

  • Check test_all.sh is passed. Answer: It doesn't, but it's not my fault

  • Add fix #{ISSUE_NUMBER} if the corresponding issue exists.

  • Fill out ## Changelog section. If the change is for only internal use, please write None to the section.

Changelog

  • gige::enumerate_cameras requires an IP address of the host to listen to cameras from
  • Very naive GigE implemented

@romainreignier

Copy link
Copy Markdown

Hi @WhiteBlackGoose
Thanks for this work. I have tested your sample app on an Imperx C4110C GigE camera and it works!

@romainreignier

romainreignier commented Jan 24, 2025

Copy link
Copy Markdown

Hi @WhiteBlackGoose
I have tested a simple application where I do Software Triggers in a loop and retrieve the image, based on the stream.rs example of this repo:

use std::{net::Ipv4Addr, str::FromStr};

fn main() {
    let local_ip_addr = Ipv4Addr::from_str("192.168.12.1").unwrap();
    let mut cameras = cameleon::gige::enumerate_cameras(local_ip_addr).unwrap();
    if cameras.is_empty() {
        println!("no camera found!");
        return;
    }
    println!("Found {} cameras", cameras.len());

    let mut camera = cameras.pop().unwrap();
    camera.open().unwrap();
    camera.load_context().unwrap();
    {
        let mut ctxt = camera.params_ctxt().unwrap();
        ctxt.node("PixelFormat")
            .unwrap()
            .as_enumeration(&ctxt)
            .unwrap()
            .set_entry_by_symbolic(&mut ctxt, "BayerRG8")
            .unwrap();
        ctxt.node("TriggerActivation")
            .unwrap()
            .as_enumeration(&ctxt)
            .unwrap()
            .set_entry_by_symbolic(&mut ctxt, "RisingEdge")
            .unwrap();
        ctxt.node("TriggerSource")
            .unwrap()
            .as_enumeration(&ctxt)
            .unwrap()
            .set_entry_by_symbolic(&mut ctxt, "Software")
            .unwrap();
        ctxt.node("TriggerMode")
            .unwrap()
            .as_enumeration(&ctxt)
            .unwrap()
            .set_entry_by_symbolic(&mut ctxt, "On")
            .unwrap();
    }
    let payload_rx = camera.start_streaming(3).unwrap();

    std::thread::sleep(std::time::Duration::from_millis(500));
    for i in 0..10 {
        {
            println!("TriggerSoftware {}", i + 1);
            let mut ctxt = camera.params_ctxt().unwrap();
            ctxt.node("TriggerSoftware")
                .unwrap()
                .as_command(&ctxt)
                .unwrap()
                .execute(&mut ctxt)
                .unwrap();
        }
        let payload = match payload_rx.recv_blocking() {
            Ok(payload) => payload,
            Err(e) => {
                println!("payload receive error: {e}");
                continue;
            }
        };
        println!(
            "payload received! block_id: {:?}, timestamp: {:?}",
            payload.id(),
            payload.timestamp()
        );
        if let Some(image_info) = payload.image_info() {
            println!("{:?}\n", image_info);
        }

        payload_rx.send_back(payload);

        std::thread::sleep(std::time::Duration::from_millis(500));
    }

    println!("Capture Loop Finished");
    camera.close().unwrap();
    println!("End of main");
}

But I have 2 issues:

  1. The main never exits. The code is stuck in camera.close().
  2. Most of the time, the code stay blocked on the payload_rx.recv_blocking() line on a given iteration, not always the same, between 1 and 10.

Edit: I have tried the stream.rs example (by replacing the enumerate_cameras) and the 2 issues are gone. But I see that the block_id often ends with the value 11 instead of 10 because one of the block is missing.
Example with missing block 2:

payload received! block_id: 1, timestamp: 25.131709855s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 3, timestamp: 25.152710121s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 4, timestamp: 25.163210255s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 5, timestamp: 25.173710389s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 6, timestamp: 25.184210521s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 7, timestamp: 25.194710655s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 8, timestamp: 25.205210789s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 9, timestamp: 25.215710921s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 10, timestamp: 25.226211055s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

payload received! block_id: 11, timestamp: 25.236711189s
ImageInfo { width: 4112, height: 3008, x_offset: 0, y_offset: 0, pixel_format: BayerRG8, image_size: 12368896 }

@WhiteBlackGoose

Copy link
Copy Markdown
Author

Hey @romainreignier

Edit: I have tried the stream.rs example (by replacing the enumerate_cameras) and the 2 issues are gone

What did you replace it with? I'm not sure I understand.

But I see that the block_id often ends with the value 11 instead of 10 because one of the block is missing.

Turn on warning level in your logger and see if you're getting lost packet warnings (packets are build here. As per GigE, one could implement retrieving lost packets (of course, the camera should support it) or interpolate the missing information, but I haven't done any of it.

I don't have another camera right now that I can test with, but soon I'll get my hands on more GigE cameras and will be able to fix some issues as they arise. Can't guarantee yours will be fixed sadly. GigE is a huge protocol.

@romainreignier

Copy link
Copy Markdown

Thanks for your reply.

What did you replace it with? I'm not sure I understand.

I have replaced the u3v enumerate with:

let local_ip_addr = Ipv4Addr::from_str("192.168.12.1").unwrap();
    let mut cameras = cameleon::gige::enumerate_cameras(local_ip_addr).unwrap();

As per GigE, one could implement retrieving lost packets.

That might help, indeed. I have tried the same Genicam commands with aravis and I had all the frames. I might compare the two wireshark captures.

@romixlab

romixlab commented Jul 6, 2025

Copy link
Copy Markdown

Great work!
Just tested on Lucid PHX051S-CC and it works as well.

@benjaminpotter

Copy link
Copy Markdown

Is there still an appetite from the maintainers for bringing this PR home? Thanks for all the work so far.

@samuelint

Copy link
Copy Markdown

Is this going to be merged soon? I would really need this in my project

@WhiteBlackGoose

Copy link
Copy Markdown
Author

@samuelint this is probably never going to be merged unless someone bothers to implement the full version. However, you can freely use this fork directly instead.

@samuelint

Copy link
Copy Markdown

@samuelint this is probably never going to be merged unless someone bothers to implement the full version. However, you can freely use this fork directly instead.

What remains to be completed for this to be considered fully implemented?

yawara added a commit to yawara/cameleon that referenced this pull request Feb 26, 2026
Co-authored-by: Yoshitomo Nakanishi <yurayura.rounin.3@gmail.com>
Co-authored-by: WhiteBlackGoose <wbg@angouri.org>
@yawara yawara mentioned this pull request Feb 26, 2026
3 tasks
yawara added a commit to yawara/cameleon that referenced this pull request Feb 26, 2026
Co-authored-by: Yoshitomo Nakanishi <yurayura.rounin.3@gmail.com>
Co-authored-by: WhiteBlackGoose <wbg@angouri.org>
yawara added a commit to yawara/cameleon that referenced this pull request Feb 26, 2026
Co-authored-by: Yoshitomo Nakanishi <yurayura.rounin.3@gmail.com>
Co-authored-by: WhiteBlackGoose <wbg@angouri.org>
yawara added a commit to yawara/cameleon that referenced this pull request Feb 26, 2026
Co-authored-by: Yoshitomo Nakanishi <yurayura.rounin.3@gmail.com>
Co-authored-by: WhiteBlackGoose <wbg@angouri.org>
yawara added a commit to yawara/cameleon that referenced this pull request Feb 26, 2026
Co-authored-by: Yoshitomo Nakanishi <yurayura.rounin.3@gmail.com>
Co-authored-by: WhiteBlackGoose <wbg@angouri.org>
yawara added a commit to yawara/cameleon that referenced this pull request Feb 26, 2026
Co-authored-by: Yoshitomo Nakanishi <yurayura.rounin.3@gmail.com>
Co-authored-by: WhiteBlackGoose <wbg@angouri.org>
Gagnon06 pushed a commit to Femtum/cameleon that referenced this pull request May 22, 2026
Co-authored-by: Yoshitomo Nakanishi <yurayura.rounin.3@gmail.com>
Co-authored-by: WhiteBlackGoose <wbg@angouri.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants