2

I am building my first application with GStreamer, and my task is to get a stream from the internet, modify it (change pixels) with use of CUDA to compute frame in parallel, and output modified stream.

For simplicity, for now I use the MP4 video to read and write on disk and don't use CUDA.

I've found an example on this site:

https://fossies.org/linux/gst-plugins-base/tests/examples/app/appsink-src.c

to lay out the structure. Source and sink pipelines as arguments to gst_parse_launch():

"filesrc location=\"%s\" ! appsink name=testsink", input_filename
"appsrc name=testsource ! filesink location=\"%s\"", output_filename

The program works when no changes done to frames. But when I try to set the values in GstMapInfo.data, I can not open the video any more:

Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file.

I was given a hint to use decoding, and I've found a decodebin element and added it to source pipeline without modifying sink:

"filesrc location=\"%s\" ! decodebin ! appsink name=testsink", input_filename

After that program works a lot longer and crashes with error:

(CudaGStreamer.exe:8428): GLib-ERROR **: gmem.c:100: failed to allocate 3110507 bytes

I've searched on google for the problem, but haven't found a solution yet, so I wondered maybe you can tell me what I am doing wrong.

Versions:

Code: https://pastebin.com/GTSiaFXd

Community
  • 1
  • 1
Arsel Muginov
  • 83
  • 3
  • 6

2 Answers2

1
  1. It does not work when you modify the data without using a decodbin because you are corruptiong the compressed binary data. Media player fails to play the stream because you have corrupted it.
  2. You are getting gst mem error mostly because you are not doing unref() of one of the buffer in your appsink which leads to a memory leak
prashanthns
  • 339
  • 2
  • 12
  • I tried to gst_object_unref() or gst_buffer_unref() one of them, getting assertion failed errors (G_IS_OBJECT or GST_IS_BUFFER) – Arsel Muginov Nov 18 '17 at 13:11
1

After more digging I solved it.

First I uncommented the following line to see what happens and "magically" it stops my program to fall from allocation error:

/* uncomment the next line to block when appsrc has buffered enough */
g_object_set (testsource, "block", TRUE, NULL);

Then I noticed that output video is still not playable and decided that the stream on second pipeline needs encoding (because in first pipeline decoding is done) to write actual MP4 video.

I took commands from:

How to convert I420 frames to BGRA format with gst-launch-1.0?

and

Gstreamer-1.0: mux raw video in a mp4 container

to get sink pipeline:

"appsrc name=testsource ! "
"videoparse width=560 height=320 format=i420 framerate=24/1 ! "
"autovideoconvert ! x264enc ! h264parse ! mp4mux ! "
"filesink location=\"%s\"",
output_filename

All is left is to get width and height from source video.

Here is a working example (it still needs tweaking): https://pastebin.com/J6pPcTjN

Edit:

I worked with code more, got 30 MB video and got allocation error again. Memory leaks? Whenever I try to free or unref a pointer that not freed or unref'd, I get various errors, maybe it should be done in another way? I'm confused.

Arsel Muginov
  • 83
  • 3
  • 6