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