basler / gst-plugin-pylon

The official GStreamer plug-in for Basler cameras
BSD 3-Clause "New" or "Revised" License
42 stars 10 forks source link

Pylon Metadata is NULL after using Videoscale or Videoconvert elements #126

Open zacharynevin-stemcell opened 1 month ago

zacharynevin-stemcell commented 1 month ago

Describe the bug

Elements downstream of the videoscale element has the Pylon metadata as NULL.

To Reproduce Set up an example pipeline with a videoscale element. Two identity elements are used to print the GstPylonMeta data. An example script is pasted below:

#include <gst/gst.h>
#include <gst/pylon/gstpylonmeta.h>
#include <iostream>

void print_pymeta(GstElement * identity, GstBuffer * buffer, gpointer udata) {
    std::cout << "New frame..." << std::endl;

    GstPylonMeta *pymeta = NULL;
    pymeta = (GstPylonMeta*)gst_buffer_get_meta(buffer, GST_PYLON_META_API_TYPE);

    if (pymeta == NULL) {
        std::cout << "> pymeta is NULL!" << std::endl;
        return;
    }

    std::cout << "> pymeta exists" << std::endl;

    gchar *meta_str = NULL;
    meta_str = g_strdup_printf(
        "> ID/img_num/skipped_num %lu/%lu/%lu\noffset %lu/%lu\npylon_timestamp "
        "%16lu\n",
        pymeta->block_id, pymeta->image_number, pymeta->skipped_images,
        pymeta->offset.offset_x, pymeta->offset.offset_y, pymeta->timestamp);

    std::cout << meta_str << std::endl;

    g_free(meta_str);
}

int main() {
    gst_init(NULL, NULL);

    GMainLoop *loop;
    GstElement* pipe;

    GstElement *cam, *identity0, *scale, *identity1, *fakesink;
    GstCaps *camcaps, *scalecaps;

    loop = g_main_loop_new(NULL, false);

    pipe = gst_pipeline_new("Test");

    cam = gst_element_factory_make("pylonsrc", NULL);
    camcaps = gst_caps_new_simple(
            "video/x-raw", 
            "width", G_TYPE_INT, 2592, 
            "height", G_TYPE_INT, 2048, 
            "format", G_TYPE_STRING, "RGB", 
            NULL);

    identity0 = gst_element_factory_make("identity", NULL);
    scale = gst_element_factory_make("videoscale", NULL);
    identity1 = gst_element_factory_make("identity", NULL);
    fakesink = gst_element_factory_make("fakesink", NULL);
    g_signal_connect(identity0, "handoff", G_CALLBACK(print_pymeta), NULL);
    g_signal_connect(identity1, "handoff", G_CALLBACK(print_pymeta), NULL);

    scalecaps = gst_caps_new_simple("video/x-raw",  "width", G_TYPE_INT, 600, "height", G_TYPE_INT, 400, NULL);

    gst_bin_add_many(GST_BIN(pipe), cam, identity0, scale, identity1, fakesink, NULL);
    gst_element_link_filtered(cam, identity0, camcaps);
    gst_element_link(identity0, scale);
    gst_element_link_filtered(scale, identity1, scalecaps);
    gst_element_link(identity1, fakesink);

    auto ret = gst_element_set_state(pipe, GST_STATE_PLAYING);
    g_main_loop_run(loop);
}

Expected behavior

Both handoff signal callbacks should print the Pylon metadata.

Instead, in the callback for the identity1 element (which is connected to the videoscale element), the Pylon metadata is NULL.

I'm not sure if this is relevant, but in the videoscale code on GitHub, the gst_video_scale_transform_meta function does a check to see if the metadata has the tags {GST_META_TAG_VIDEO_STR,GST_META_TAG_VIDEO_COLORSPACE_STR,...,}. Meanwhile in the gstpylonmeta.cpp file, the tag GST_META_TAG_VIDEO_STR is assigned to the the Pylon metadata.

// gst/videoscale/gstvideoscale.c [line 519]
const gchar *const valid_tags[] = { GST_META_TAG_VIDEO_STR,
    GST_META_TAG_VIDEO_COLORSPACE_STR,
    GST_META_TAG_VIDEO_ORIENTATION_STR,
    GST_META_TAG_VIDEO_SIZE_STR
};
// gst/pylon/gstpylonmeta.cpp [line 59]
static const gchar *tags[] = {GST_META_TAG_VIDEO_STR, NULL};

Environment