Stream video to a SDL_texture

Miguel Silvestre msilvestre at gmail.com
Thu Apr 20 14:50:37 UTC 2023


Hi all,

I don't know if this is the proper place for this.

But I'm having some trouble using SDL and gstreamer.

I want to stream a video (just the video) on a SDL_texture.

Here is what I am doing:

```
    auto pipeline = gst_pipeline_new ("audio-player");
    auto videoSrc = gst_element_factory_make("videotestsrc", "video_src");
    auto videoConvert = gst_element_factory_make("videoconvert",
"video_convert");
    auto videoSink = GST_APP_SINK(gst_element_factory_make("appsink",
"video_sink"));

   gst_app_sink_set_emit_signals(videoSink, true);
/ Get the sink pad of the videoconvert element
    GstPad *sinkPad = gst_element_get_static_pad(videoConvert, "sink");

// Create a new caps object with the desired capabilities
    GstCaps *caps = gst_caps_new_simple("video/x-raw",
                                        "format", G_TYPE_STRING, "RGBA",
                                        NULL);

// Set the capabilities on the sink pad
    gst_pad_set_caps(sinkPad, caps);

// Release the caps object
    gst_caps_unref(caps);

    g_signal_connect(videoSink, "new-sample", G_CALLBACK(onNewSample),
this);
    g_signal_connect(videoSink, "eos", G_CALLBACK(onEos), this);
    //videoSink = gst_element_factory_make("autovideosink", "video_sink");

    gst_bin_add_many(GST_BIN (pipeline),
                     videoSrc,
                     videoConvert,
                     videoSink,
                     NULL);
    gst_element_link_many (videoSrc, videoConvert, videoSink, NULL);

```

Then on my main loop I try to get the data buffer from the appsink and set
it to a texture:

```
    if (!_hasNewSample)
        return;

    GstSample* sample = gst_app_sink_pull_sample(videoSink);
    {
        std::lock_guard<std::mutex> lock(StreamGstreamerActivityUI::_mutex);
        _hasNewSample = false;
    }
    GstBuffer* buffer = gst_sample_get_buffer(sample);
    if (!buffer)
    {
        std::cout << ">>>>> Buffer is null!\n";
        return;
    }

    GstMapInfo info;
    gst_buffer_map(buffer, &info, GST_MAP_READ);
    GstCaps* caps = gst_sample_get_caps(sample);
    if (!caps)
    {
        std::cout << ">>>>> Caps is null!\n";
        return;
    }

// Get the structure for the first media type in the caps
    GstStructure* structure = gst_caps_get_structure(caps, 0);
    if (!structure)
    {
        std::cout << ">>>>> Structure is null!\n";
        return;
    }

// Get the width and height fields from the structure
    int width, height;
    gst_structure_get_int(structure, "width", &width);
    gst_structure_get_int(structure, "height", &height);


    if (!_texture)
    {
        _texture = SDL_CreateTexture(Display::getRenderer(),
SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING,
                                     width, height);
        SDL_UpdateTexture(_texture, NULL, info.data, height);
        SDL_RenderCopy(Display::getRenderer(), _texture, NULL, NULL);
        return;
    }

    SDL_LockTexture(_texture, NULL, &_rawPixels, &_rawPitch);
//Copy to locked pixels
    memcpy(_rawPixels, info.data, _rawPitch * height);
    SDL_UnlockTexture(_texture);
    _rawPixels = NULL;
    _rawPitch = 0;
// Render the texture

    auto previousTarget = SDL_GetRenderTarget(Display::getRenderer());
    SDL_SetRenderTarget(Display::getRenderer(), _texture);

    SDL_RenderCopy(Display::getRenderer(), _texture, NULL, NULL);
    SDL_RenderPresent( Display::getRenderer() );

    SDL_SetRenderTarget(Display::getRenderer(), previousTarget);

    // free gst stuff
    gst_sample_unref(sample);
    gst_buffer_unref(buffer);
    gst_caps_unref(caps);
```
And this is my callback functions:
```

void StreamGstreamerActivityUI::onNewSample(GstAppSink *sink, gpointer
userData)
{
    static auto sampleCount = 0;
    auto streamActivity = static_cast<StreamGstreamerActivityUI*>(userData);
    std::cout << ">>>>>>>>>>>>>> New Sample: " << ++sampleCount << "!\n";
    std::lock_guard<std::mutex> lock(StreamGstreamerActivityUI::_mutex);
    _hasNewSample = true;
}


void StreamGstreamerActivityUI::onEos(GstAppSink *sink, gpointer userData)
{
    std::cout << ">>>>>>>>>>>>>> End of Sample!\n";
    std::lock_guard<std::mutex> lock(StreamGstreamerActivityUI::_mutex);
    _hasNewSample = false;
}
```

I'm surely doing something wrong. because I don't see any output on the SDL
window and I got plenty of critical stuff from gst like this:

```
>>>>>>>>>>>>>> New Sample: 1!
>>>>>>>>>>>>>> New Sample: 2!
>>>>>>>>>>>>>> New Sample: 3!
>>>>>>>>>>>>>> New Sample: 4!
>>>>>>>>>>>>>> New Sample: 5!
>>>>>>>>>>>>>> New Sample: 6!
>>>>>>>>>>>>>> New Sample: 7!
>>>>>>>>>>>>>> New Sample: 8!
>>>>>>>>>>>>>> New Sample: 9!
>>>>>>>>>>>>>> New Sample: 10!
>>>>>>>>>>>>>> New Sample: 11!

(ProjectX.exe:31760): GStreamer-CRITICAL **: 15:37:49.790:
gst_mini_object_unlock: assertion 'state >= SHARE_ONE' failed

(ProjectX.exe:31760): GStreamer-CRITICAL **: 15:37:49.790:
gst_mini_object_unref: assertion 'GST_MINI_OBJECT_REFCOUNT_VA
LUE (mini_object) > 0' failed

(ProjectX.exe:31760): GStreamer-CRITICAL **: 15:37:49.811:
gst_mini_object_unlock: assertion 'state >= SHARE_ONE' failed

(ProjectX.exe:31760): GStreamer-CRITICAL **: 15:37:49.811:
gst_mini_object_unref: assertion 'GST_MINI_OBJECT_REFCOUNT_VA
LUE (mini_object) > 0' failed
```


Any thoughts or some direction on how I can achieve this?

Thank you.

--
Miguel Silvestre
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20230420/f2cbfc33/attachment.htm>


More information about the gstreamer-devel mailing list