<div>I'm trying to play video stream over the network, but before that I test my pipeline with local video file.</div><div> </div><div>My first try is this and works fine.</div><div> gst-launch filesrc location=test.avi ! decodebin2 ! ffmpegcolorspace ! autovideosink<br>
</div><div>My second try also works fine, too. </div><div>The video_only.mpeg2 file is a video file without container information, i.e., only included raw video data.</div><div> gst-launch filesrc location=video_only.mpeg2 ! mpegvideoparse ! ffdec_mpeg2video ! ffmpegcolorspace ! autovideosink<br>
</div><div>I have trouble when I run the code above using appsrc. I got error message : "Error Internal data flow error."</div><div>Does anybody can give me any suggestions or guide reference?</div><div> </div>
<div>I asked this issue to Stackoverflow a few days ago, but no one answers. So I post the same question again.</div><div>( <a href="http://stackoverflow.com/questions/13074894/gstreamer-appsrc-video-streaming-over-the-network">http://stackoverflow.com/questions/13074894/gstreamer-appsrc-video-streaming-over-the-network</a> )</div>
<div> </div><div>I attach source code for reference.</div><div> </div><div>// <a href="http://amarghosh.blogspot.kr/2012/01/gstreamer-appsrc-in-action.html">http://amarghosh.blogspot.kr/2012/01/gstreamer-appsrc-in-action.html</a><br>
// <a href="http://www.cs.odu.edu/~cs476/Xlib/xlines.c">http://www.cs.odu.edu/~cs476/Xlib/xlines.c</a><br>/*<br> I don't know if it is syntax highlighter or blogger, but I can't seem to<br> put angle brackets around header file names properly.<br>
*/<br>#include <X11/Xlib.h><br>#include <stdio.h><br>#include <stdbool.h><br>#include <unistd.h><br>#include <gst/gst.h><br>#include <gst/app/gstappsrc.h><br>#include <gst/interfaces/xoverlay.h><br>
<br>typedef struct {<br> GstPipeline *pipeline;<br> GstAppSrc *src;<br> GstElement *queue;<br> GstElement *decoder;<br> GstElement *ffmpeg;<br> GstElement *videoscale;<br> GstElement *convertcolor;<br> GstElement *videosink;<br>
GMainLoop *loop;<br> guint sourceid;<br> FILE *file;<br>}gst_app_t;<br> <br>static gst_app_t gst_app;<br> <br>#define BUFF_SIZE (4 * 1024)</div><div>static Window child_window = 0;<br>static Window window = 0;<br> <br>
static gboolean read_data(gst_app_t *app)<br>{<br> GstBuffer *buffer;<br> guint8 *ptr;<br> gint size;<br> GstFlowReturn ret;<br> <br> ptr = g_malloc(BUFF_SIZE);<br> g_assert(ptr);<br> <br> size = fread(ptr, 1, BUFF_SIZE, app->file);<br>
<br> if(size == 0){<br> ret = gst_app_src_end_of_stream(app->src);<br> g_debug("eos returned %d at %d\n", ret, __LINE__);<br> return FALSE;<br> }<br> <br> buffer = gst_buffer_new();<br> GST_BUFFER_MALLOCDATA(buffer) = ptr;<br>
GST_BUFFER_SIZE(buffer) = size;<br> GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer);<br> <br> ret = gst_app_src_push_buffer(app->src, buffer);<br> <br> if(ret != GST_FLOW_OK){<br> g_debug("push buffer returned %d for %d bytes \n", ret, size);<br>
return FALSE;<br> }<br> <br> if(size != BUFF_SIZE){<br> ret = gst_app_src_end_of_stream(app->src);<br> g_debug("eos returned %d at %d\n", ret, __LINE__);<br> return FALSE;<br> }<br> <br> return TRUE;<br>
}<br> <br>static void start_feed (GstElement * pipeline, guint size, gst_app_t *app)<br>{<br> if (app->sourceid == 0) {<br> g_print("start feeding");<br> app->sourceid = g_idle_add ((GSourceFunc) read_data, app);<br>
}<br>}<br> <br>static void stop_feed (GstElement * pipeline, gst_app_t *app)<br>{<br> if (app->sourceid != 0) {<br> g_print("stop feeding");<br> g_source_remove (app->sourceid);<br> app->sourceid = 0;<br>
}<br>}<br> <br>static void on_pad_added(GstElement *element, GstPad *pad)<br>{<br> GstCaps *caps;<br> GstStructure *str;<br> gchar *name;<br> GstPad *ffmpegsink;<br> GstPadLinkReturn ret;<br> <br> g_debug("pad added");<br>
<br> caps = gst_pad_get_caps(pad);<br> str = gst_caps_get_structure(caps, 0);<br> <br> g_assert(str);<br> <br> name = (gchar*)gst_structure_get_name(str);<br> <br> g_debug("pad name %s", name);<br> <br> if(g_strrstr(name, "video")){<br>
<br> ffmpegsink = gst_element_get_pad(gst_app.ffmpeg, "sink");<br> g_assert(ffmpegsink);<br> ret = gst_pad_link(pad, ffmpegsink);<br> g_debug("pad_link returned %d\n", ret);<br> gst_object_unref(ffmpegsink);<br>
}<br> gst_caps_unref(caps);<br>}<br> <br>static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer *ptr)<br>{<br> gst_app_t *app = (gst_app_t*)ptr;<br> <br> switch(GST_MESSAGE_TYPE(message)){<br> <br> case GST_MESSAGE_ELEMENT:<br>
gst_x_overlay_set_window_handle (GST_X_OVERLAY (GST_MESSAGE_SRC(message)), child_window);<br> break;</div><div> case GST_MESSAGE_ERROR:{<br> gchar *debug;<br> GError *err;<br> <br> gst_message_parse_error(message, &err, &debug);<br>
g_print("Error %s\n", err->message);<br> g_error_free(err);<br> g_free(debug);<br> g_main_loop_quit(app->loop);<br> }<br> break;<br> <br> case GST_MESSAGE_WARNING:{<br> gchar *debug;<br> GError *err;<br>
gchar *name;<br> <br> gst_message_parse_warning(message, &err, &debug);<br> g_print("Warning %s\nDebug %s\n", err->message, debug);<br> <br> name = GST_MESSAGE_SRC_NAME(message);<br> <br> g_print("Name of src %s\n", name ? name : "nil");<br>
g_error_free(err);<br> g_free(debug);<br> }<br> break;<br> <br> case GST_MESSAGE_EOS:<br> g_print("End of stream\n");<br> g_main_loop_quit(app->loop);<br> break;<br> <br> case GST_MESSAGE_STATE_CHANGED:<br>
break;<br> <br> default:<br> g_print("got message %s\n", \<br> gst_message_type_get_name (GST_MESSAGE_TYPE (message)));<br> break;<br> }<br> <br> return TRUE;<br>}</div><div> </div><div>/* <br> * gst-launch filesrc location=test.avi ! decodebin2 ! ffmpegcolorspace ! autovideosink<br>
* gst-launch filesrc location=video_only.mpeg2 ! mpegvideoparse ! ffdec_mpeg2video ! ffmpegcolorspace ! autovideosink</div><div> *<br> * 1. dependency library install<br> * $ sudo apt-get install gstreamer0.10-plugins-bad<br>
* $ sudo apt-get install gstreamer0.10-ffmpeg<br> *<br> * 2. compile<br> * $ gcc hello.c -o hello -lX11 `pkg-config --cflags --libs gstreamer-0.10 gstreamer-app-0.10` -lgstinterfaces-0.10</div><div> */<br> <br>void gstreamer_init(int argc, char *argv[])<br>
{<br> gst_app_t *app = &gst_app;<br> GstBus *bus;<br> GstStateChangeReturn state_ret;<br> <br> if(argc != 2){<br> printf("File name not specified\n");<br> return;<br> }<br> <br> app->file = fopen(argv[1], "r");<br>
<br> g_assert(app->file);<br> <br> gst_init(NULL, NULL);<br> <br> app->pipeline = (GstPipeline*)gst_pipeline_new("mypipeline");</div><div> bus = gst_pipeline_get_bus(app->pipeline);<br> gst_bus_add_watch(bus, (GstBusFunc)bus_callback, app);<br>
gst_object_unref(bus);<br> <br> app->src = (GstAppSrc*)gst_element_factory_make("appsrc", "mysrc");<br>#if 0// GENERAL_VIDEO_FILE <br> app->decoder = gst_element_factory_make("decodebin2", "mydecoder");<br>
app->ffmpeg = gst_element_factory_make("ffmpegcolorspace", "myffmpeg");<br>#else<br> app->decoder = gst_element_factory_make("mpegvideoparse", "mydecoder");<br> app->ffmpeg = gst_element_factory_make("ffdec_mpeg2video", "myffmpeg");<br>
#endif<br> app->convertcolor = gst_element_factory_make("ffmpegcolorspace", "myconvert");<br> app->videosink = gst_element_factory_make("autovideosink", "myvsink");</div><div>
</div><div> g_assert(app->src);<br> g_assert(app->decoder);<br> g_assert(app->ffmpeg);<br> g_assert(app->convertcolor);<br> g_assert(app->videosink);<br> <br> g_signal_connect(app->src, "need-data", G_CALLBACK(start_feed), app);<br>
g_signal_connect(app->src, "enough-data", G_CALLBACK(stop_feed), app);<br> g_signal_connect(app->decoder, "pad-added",<br> G_CALLBACK(on_pad_added), app->decoder);<br> <br> gst_bin_add_many(GST_BIN(app->pipeline), (GstElement*)app->src,<br>
app->decoder, app->ffmpeg, app->convertcolor, app->videosink, NULL);<br> <br> if(!gst_element_link((GstElement*)app->src, app->decoder)){<br> g_warning("failed to link src anbd decoder");<br>
}<br> <br> if(!gst_element_link(app->ffmpeg, app->convertcolor)){<br> g_warning("failed to link ffmpeg and convertcolor");<br> }<br> <br> if(!gst_element_link(app->convertcolor, app->videosink)){<br>
g_warning("failed to link convertcolor and videosink");<br> }</div><div> state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_PLAYING);<br> g_warning("set state returned %d\n", state_ret);<br>
<br> app->loop = g_main_loop_new(NULL, FALSE);<br> <br> g_main_loop_run(app->loop);<br> <br> state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_NULL);<br> g_warning("set state null returned %d\n", state_ret);<br>
gst_object_unref(app->pipeline);<br> <br>}</div><div>int main(int argc, char *argv[])<br>{<br> Display *disp;<br> Window root;<br> long fgcolor, bgcolor;</div><div> GC gc;<br> XGCValues gc_val;<br> XEvent event;<br>
char *msg = "Hello, World!";<br> int screen;</div><div> disp = XOpenDisplay(NULL);<br> if (disp == NULL) {<br> fprintf(stderr, "Cannot open display\n");<br> exit(1);<br> }<br> <br> screen = DefaultScreen(disp);</div>
<div> root = RootWindow(disp, screen);<br> fgcolor = BlackPixel(disp, screen);<br> bgcolor = WhitePixel(disp, screen);</div><div> </div><div> window = XCreateSimpleWindow(disp, root, 100, 100, 1000, 840, 1,<br> fgcolor, bgcolor);</div>
<div> child_window = XCreateSimpleWindow(disp, window, 100, 100, 800, 600, 1,<br> fgcolor, bgcolor);</div><div> gc_val.foreground = fgcolor;<br> gc_val.background = bgcolor;<br> gc = XCreateGC(disp, child_window, GCForeground|GCBackground, &gc_val);</div>
<div> </div><div> XSelectInput(disp, child_window, ExposureMask | KeyPressMask);</div><div> </div><div> g_warning("map xwindow");<br> XMapWindow(disp, window);<br> XMapWindow(disp, child_window);<br> XSync(disp, FALSE);</div>
<div> </div><div> gstreamer_init(argc, argv);</div><div> </div><div> sleep(2);</div><div> XDestroySubwindows( disp, window );<br> XDestroyWindow( disp, window );</div><div> XCloseDisplay( disp );</div><div> </div><div>
return 0;<br>}</div><div> </div><div> </div><div> </div><div> </div><div> </div>