stream - Gstreamer - appsrc push model -
i'm developing c application (under linux) receives raw h.264 stream , should visualize stream using gstreamer apis. newbie gstreamer maybe doing huge stupid mistakes or ignoring well-known stuff, sorry that.
i got raw h264 video (i knew exact same format need) , developed application plays it. correctly works appsrc in pull mode (when need data called, new data file , perform push-buffer).
now i'm trying exact same thing in push mode, because don't have video, stream. have method inside code called every time new data (in form of uint8_t
buffer) arrives, , video source.
i googled problem , had @ documentation, found no simple code snippets use case, if seems simple one. understood have init pipeline , appsrc , push-buffer when have new data.
well, developed 2 methods: init_stream()
pipeline/appsrc initialization , populate_app(void *inbuf, size_t len)
send data when available. compiles , correctly runs, no video:
struct _app { gstappsrc *appsrc; gstpipeline *pipeline; gstelement *h264parse; gstelement *mfw_vpudecoder; gstelement *mfw_v4lsin; gmainloop *loop; }; typedef struct _app app; app s_app; app *app = &s_app; static gboolean bus_message (gstbus * bus, gstmessage * message, app * app) { gst_debug ("got message %s", gst_message_type_get_name (gst_message_type (message))); switch (gst_message_type (message)) { case gst_message_error: g_error ("received error"); g_main_loop_quit (app->loop); break; case gst_message_eos: g_main_loop_quit (app->loop); break; default: break; } return true; } int init_stream() { gstbus *bus; gst_init (null, null); fprintf(stderr, "gst_init done\n"); /* create mainloop messages */ app->loop = g_main_loop_new (null, true); fprintf(stderr, "app loop initialized\n"); app->pipeline = gst_parse_launch("appsrc name=mysource ! h264parse ! mfw_vpudecoder ! mfw_v4lsin", null); app->appsrc = gst_bin_get_by_name (gst_bin(app->pipeline), "mysource"); gst_app_src_set_stream_type(app->appsrc, gst_app_stream_type_stream); gst_app_src_set_emit_signals(app->appsrc, true); fprintf(stderr, "pipeline , appsrc initialized\n"); /* create bus pipeline */ bus = gst_pipeline_get_bus(app->pipeline); fprintf(stderr, "bus created\n"); /* add watch messages */ gst_bus_add_watch (bus, (gstbusfunc) bus_message, app); gst_object_unref(bus); fprintf(stderr, "bus_add_watch done\n"); gstcaps* video_caps = gst_caps_new_simple ("video/x-h264", "width", g_type_int, 800, "height", g_type_int, 480, "framerate", gst_type_fraction, 25, 1, null); gst_app_src_set_caps(gst_app_src(app->appsrc), video_caps); /* go playing , wait in mainloop. */ gst_element_set_state ((gstelement*) app->pipeline, gst_state_playing); fprintf(stderr, "gst_element_set_state play\n"); /* mainloop stopped when receive error or eos */ g_main_loop_run (app->loop); fprintf(stderr, "g_main_loop_run called\n"); gst_element_set_state ((gstelement*) app->pipeline, gst_state_null); fprintf(stderr, "gst_element_set_state gst_state_null\n"); /* free file */ // g_mapped_file_unref (app->file); gst_object_unref (bus); g_main_loop_unref (app->loop); return 0; } void populateapp(void *inbuf , size_t len) { guint8 *_buffer = (guint8*) inbuf; gstflowreturn ret; gstbuffer *buffer = gst_buffer_new(); gstcaps* video_caps = gst_caps_new_simple ("video/x-h264", "width", g_type_int, 800, "height", g_type_int, 480, "framerate", gst_type_fraction, 25, 1, null); gst_buffer_set_caps(buffer, video_caps); gst_buffer_data (buffer) = _buffer; gst_buffer_size (buffer) = len; // g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret); ret = gst_app_src_push_buffer(gst_app_src(app->appsrc), buffer); gst_buffer_unref (buffer); }
as said, total newbie @ gstreamer there's lot of cut-and-paste code internet, imho should work. see issues?
it's not clear how calling populateapp, need call repeatedly have data push pipeline. can done in separate thread 1 blocked g_main_loop_run, or can restructure program avoid using gmainloop.
Comments
Post a Comment