Kenny D.
Kenny D.

Reputation: 33

Gstreamer. Write appsink to filesink

I have written a code for appsrc to appsink and it works. I see the actual buffer. It's encoded in H264(vpuenc=avc). Now I want to save it in a file(filesink). How I approach it?

app:

int main(int argc, char *argv[]) {

gst_init (NULL, NULL);

GstElement *pipeline, *sink;
gchar *descr;
GError *error = NULL;
GstAppSink *appsink;

descr = g_strdup_printf ( 
    "mfw_v4lsrc device=/dev/video1 capture_mode=0 !  "  // grab from mipi camera
    "ffmpegcolorspace ! vpuenc codec=avc ! "
    "appsink name=sink"
); 
pipeline = gst_parse_launch (descr, &error);
if (error != NULL) {
    g_print ("could not construct pipeline: %s\n", error->message);
    g_error_free (error);
    exit (-1);
}

gst_element_set_state(pipeline, GST_STATE_PAUSED);
sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
appsink = (GstAppSink *) sink;
gst_app_sink_set_max_buffers ( appsink, 2); // limit number of buffers queued
gst_app_sink_set_drop( appsink, true ); // drop old buffers in queue when full

gst_element_set_state (pipeline, GST_STATE_PLAYING);


int i = 0;
while( !gst_app_sink_is_eos(appsink) )
{

    GstBuffer *buffer = gst_app_sink_pull_buffer(appsink);
    uint8_t* data = (uint8_t*)GST_BUFFER_DATA(buffer);
    uint32_t size = GST_BUFFER_SIZE(buffer);

    gst_buffer_unref(buffer);
}
return 0; }

Upvotes: 0

Views: 7915

Answers (3)

mpr
mpr

Reputation: 3378

If as mentioned in the comments, what you actually want to know is how to do a network video stream in GStreamer, you should probably close this question because you're on the wrong path. You don't need to use an appsink or filesink for that. What you'll want to investigate are the GStreamer elements related to RTP, RTSP, RTMP, MPEGTS, or even MJPEGs (if your image size is small enough).

Here are two basic send/receive video stream pipelines:

gst-launch-0.10 v4l2src ! ffmpegcolorspace ! videoscale ! video/x-raw-yuv,width=640,height=480 ! vpuenc ! h264parse ! rtph264pay ! udpsink host=localhost port=5555

gst-launch-0.10 udpsrc port=5555 ! application/x-rtp,encoding-name=H264,payload=96 ! rtph264depay ! h264parse ! ffdec_h264 ! videoconvert ! ximagesink

Upvotes: 1

mpr
mpr

Reputation: 3378

In this situation you don't write your own while loop. You register callbacks and wait for buffers (GStreamer 0.10) to arrive. If you're using GStreamer 1.0, you use samples instead of buffers. Samples are a huge pain in the ass compared to buffers but oh well.

Register the callback:

GstAppSinkCallbacks* appsink_callbacks = (GstAppSinkCallbacks*)malloc(sizeof(GstAppSinkCallbacks));
appsink_callbacks->eos = NULL;
appsink_callbacks->new_preroll = NULL;
appsink_callbacks->new_sample = app_sink_new_sample;
gst_app_sink_set_callbacks(GST_APP_SINK(appsink), appsink_callbacks, (gpointer)pointer_to_data_passed_to_the_callback, free);

And your callback:

GstFlowReturn app_sink_new_sample(GstAppSink *sink, gpointer user_data) {
  prog_data* pd = (prog_data*)user_data;

  GstSample* sample = gst_app_sink_pull_sample(sink);

  if(sample == NULL) {
    return GST_FLOW_ERROR;
  }

  GstBuffer* buffer = gst_sample_get_buffer(src);

  GstMemory* memory = gst_buffer_get_all_memory(buffer);
  GstMapInfo map_info;

  if(! gst_memory_map(memory, &map_info, GST_MAP_READ)) {
    gst_memory_unref(memory);
    gst_sample_unref(sample);
    return GST_FLOW_ERROR;
  }

  //render using map_info.data

  gst_memory_unmap(memory, &map_info);
  gst_memory_unref(memory);
  gst_sample_unref(sample);

  return GST_FLOW_OK;
}

You can keep your while loop as it is--using gst_app_sink_is_eos()--but make sure to put a sleep in it. Most of the time I use something like the following instead:

GMainLoop* loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);

Note: Unless you need to do something special with the data you can use the "filesink" element directly.

Upvotes: 1

Prabhakar Lad
Prabhakar Lad

Reputation: 1438

Simpler option would be write to the file directly in the appsink itself ie when you get a callback when the buffer is done write to the file and make sure you close it on eos.

Hope that helps.

Upvotes: 0

Related Questions