Hi,
I am trying to play multiple videos [mov/mp4/mpeg-ts container, H.264/MPEG2 Video Codec] using a sample gstreamer application, [This application runs as a single process spawning multiple threads] simultaneously using GStreamer-vaapi and libVA-1.0.7. The driver used for hardware acceleration of video is "i965". Following is the result of "vainfo": ------------------------------------------------------------------ libva: libva version 0.31.1 libva: va_getDriverName() returns 0 libva: Trying to open /opt/X11R7/lib/dri/i965_drv_video.so libva: va_openDriver() returns 0 vainfo: VA API version: 0.31 vainfo: Driver version: i965 Driver 0.1 vainfo: Supported profile and entrypoints VAProfileMPEG2Simple : VAEntrypointVLD VAProfileMPEG2Main : VAEntrypointVLD VAProfileH264Baseline : VAEntrypointVLD VAProfileH264Main : VAEntrypointVLD VAProfileH264High : VAEntrypointVLD VAProfileVC1Simple : VAEntrypointVLD VAProfileVC1Main : VAEntrypointVLD VAProfileVC1Advanced : VAEntrypointVLD ------------------------------------------------------------------ In the sample application I am creating multiple windows using "XCreateWindow" and passing the generated window ID to vaapisink. There following is the problem that I am facing: The application crashes randomly: None of the gstreamer calls return a failure and the state is getting changed to play successfully. Tried the application with different container formats. Also from the command line using "gst-launch" I am able to playback multiple videos simultaneously. [Here one difference compared to the sample application is, these are running as separate processes] Following is the backtrace of the gdb : ------------------------------------------------------------------ 0xb7fe856c in do_bo_emit_reloc () from /opt/X11R7//lib/libdrm_intel.so.1 #1 0xb7fe882a in drm_intel_gem_bo_emit_reloc () from /opt/X11R7//lib/libdrm_intel.so.1 #2 0xb7fe36da in drm_intel_bo_emit_reloc () from /opt/X11R7//lib/libdrm_intel.so.1 #3 0xb130fe3b in intel_batchbuffer_emit_reloc_helper (ctx=, batch=0xaf2beb30, bo=0x0, read_domains=16, write_domains=0, delta=0) at intel_batchbuffer.c:198 #4 0xb1317a19 in gen6_emit_wm_state (ctx=0xaf2bc178, kernel=) at i965_render.c:1808 #5 gen6_render_emit_states (ctx=0xaf2bc178, kernel=) at i965_render.c:1894 #6 0xb1318f85 in gen6_render_put_surface (ctx=0xaf2bc178, surface=67108868, srcx=0, srcy=0, srcw=1280, srch=720, destx=0, desty=0, destw=940, desth=528, flag=0) at i965_render.c:1921 #7 intel_render_put_surface (ctx=0xaf2bc178, surface=67108868, srcx=0, srcy=0, srcw=1280, srch=720, destx=0, desty=0, destw=940, desth=528, flag=0) at i965_render.c:2020 #8 0xb131b082 in i965_PutSurface (ctx=0xaf2bc178, surface=67108868, draw=0x3e00007, srcx=0, srcy=0, srcw=1280, srch=720, destx=0, desty=0, destw=940, desth=528, cliprects=0x0, number_cliprects=0, flags=0) at i965_drv_video.c:1772 #9 0xb4902796 in vaPutSurface (dpy=0xaf2bc008, surface=67108868, draw=65011719, srcx=0, srcy=0, srcw=1280, srch=720, destx=0, desty=0, destw=940, desth=528, cliprects=0x0, number_cliprects=0, flags=0) at va_x11.c:288 #10 0xb490ad15 in gst_vaapi_window_x11_render (window=0xb0cc05f8, surface=0xa95bcc70, src_rect=0xa94fe988, dst_rect=0xaf246598, flags=3) at gstvaapiwindow_x11.c:424 #11 0xac25a820 in gst_vaapi_window_put_surface (window=0xb0cc05f8, surface=0xa95bcc70, src_rect=0xa94fe988, dst_rect=0xaf246598, flags=3) at gstvaapiwindow.c:506 #12 0xb492f2f4 in gst_vaapisink_show_frame_x11 (base_sink=0xaf2463d8, buffer=0xb65dd6a8) at gstvaapisink.c:680 #13 gst_vaapisink_show_frame (base_sink=0xaf2463d8, buffer=0xb65dd6a8) at gstvaapisink.c:714 #14 0x4d782435 in gst_base_sink_render_object (basesink=0xaf2463d8, pad=0xaf2ae998, is_list=0, obj=0xb65dd6a8) at gstbasesink.c:2833 #15 0x4d783eb7 in gst_base_sink_queue_object_unlocked (basesink=0xaf2463d8, pad=0xaf2ae998, is_list=0, obj=0xb65dd6a8, prerollable=1) at gstbasesink.c:3111 #16 0x4d78a599 in gst_base_sink_chain_unlocked (basesink=0xaf2463d8, pad=0xaf2ae998, is_list=0, obj=0xb65dd6a8) at gstbasesink.c:3485 #17 0x4d78aa99 in gst_base_sink_chain_main (basesink=, pad=0xaf2ae998, is_list=0, obj=0xb65dd6a8) at gstbasesink.c:3523 #18 0x4cad55cd in gst_pad_chain_data_unchecked (pad=0xaf2ae998, is_buffer=1, data=0xb65dd6a8) at gstpad.c:4190 #19 0x4cad5fe7 in gst_pad_push_data (pad=0xace0c580, is_buffer=1, data=0xb65dd6a8) at gstpad.c:4419 #20 0xb493427a in gst_vaapidecode_step (pad=0xaf20a268, buf=0xa8313770) at gstvaapidecode.c:162 #21 gst_vaapidecode_chain (pad=0xaf20a268, buf=0xa8313770) at gstvaapidecode.c:536 #22 0x4cad55cd in gst_pad_chain_data_unchecked (pad=0xaf20a268, is_buffer=1, data=0xa8313770) at gstpad.c:4190 #23 0x4cad5fe7 in gst_pad_push_data (pad=0xaf2ae8d0, is_buffer=1, data=0xa8313770) at gstpad.c:4419 #24 0xb662ada6 in gst_queue_push_one (pad=0xaf2ae8d0) at gstqueue.c:1144 #25 gst_queue_loop (pad=0xaf2ae8d0) at gstqueue.c:1260 #26 0x4cb040f1 in gst_task_func (task=0xaf21f5a8) at gsttask.c:271 #27 0x4cb05727 in default_func (tdata=0xaf201a40, pool=0xb6509408) at gsttaskpool.c:70 #28 0x4b9e4214 in ?? () from /lib/libglib-2.0.so.0 #29 0x4b9e2210 in ?? () from /lib/libglib-2.0.so.0 #30 0x4b91b919 in start_thread () from /lib/libpthread.so.0 #31 0x4b85de5e in clone () from /lib/libc.so.6 ------------------------------------------------------------------ I am using the following packages as mentioned on Intel Linux graphics site "http://intellinuxgraphics.org/2010Q4.html". Apart from this I have installed the following gstreamer packages: gstreamer-0.10.31 gst-plugins-base-0.10.29 gst-plugins-good-0.10.22 gst-plugins-bad-0.10.19 gst-plugins-ugly-0.10.15 gst-ffmpeg-0.10.10 gstreamer-vaapi-latest(downloaded from http://www.splitted-desktop.com/~gbeauchesne/gstreamer-vaapi/). For reference attaching the sample application(MultiVideos.c). I am not sure if it is application problem or plugin or driver limitation or X? As the same application runs with "ximagesink" and software decoder like ffmpeg. What could be the problem? PS: OS : Fedora Core 13 Kernel : 2.6.37 Platform: Intel i5, Sandy Bridge Regards, Jyotsana. /* Sample application to run multiple videos. Files to be played are hardcorded in the code with the variable "FileName". */ /* Application supports mov/mpegts container formats, video codec : mpeg2 or h264. Audio not supported in this application.*/ /* To compile the application do: */ /* gcc -I/usr/include/gstreamer-0.10 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libxml2 -I/usr/lib/liboil-0.3 -I/usr/include -L/usr/lib/gstreamer-0.10 -lglib-2.0 -lgmodule-2.0 -lgstreamer-0.10 -lxml2 -lgobject-2.0 -lgthread-2.0 -lgstbase-0.10 -lX11 -lgstinterfaces-0.10 -lgstvaapi-x11-0.10 -lgstvaapi-0.10 MultiVideo_post.c -o MultiVideo */ /**************************************************************************************************************************************************/ /*------------------------------ System Includes -----------------------------*/ #include <string.h> #include <gst/gst.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #include <pthread.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <gst/interfaces/xoverlay.h> /*------------------------------ Macros -----------------------------*/ #define MAX_VIDEOS 4 /* Maximum number of videos that can be played.*/ #define NOOFWINDOWS 4 /* Max No of windows that can be created simultaneously. Range is 1-4 */ #define MPEGTS 0 /* To playback mpegts files */ #define MOV 1 /* To playback mov/mp4 files */ /* Right now files are hardcoded for mov filescan be changed to ts files */ #define ENABLE_DBGPRINT 0 /* Macro to enable printf*/ /* Macro for printf */ #if (1 == ENABLE_DBGPRINT) #define PRINT(fmt, args...) \ printf("\n DEBUG : TEST => %s : %s:\n " fmt "\n", __FILE__, __FUNCTION__ , ## args); #else #define PRINT(fmt, args...) #endif/*!< #if(1 == ENABLE_DBGPRINT) */ /*------------------------------ Global variables -----------------------------*/ /*Instance of the displayplay connection*/ Display *display; /*Files to be played*/ char FileName[MAX_VIDEOS][256] = {"City Video Clips _1280.mov", "City Video Clips _1280.mov", "City Video Clips _1280.mov", "City Video Clips _1280.mov"}; /*Variables for setting the window location, width and height */ int x[MAX_VIDEOS] = {0, 550, 0, 550}; int y[MAX_VIDEOS] = {0, 0, 550 , 550}; int width[MAX_VIDEOS] = {500, 500, 500, 500}; int height[MAX_VIDEOS] = {500, 500, 500, 500}; /*------------------------------ Structure Declaration -----------------------------*/ /*Holds general info like window ID, width , height etc.*/ typedef struct _tag_APP_GENERALINFO_ST { Window win; int x; int y; int width; int height; char currentfilename[256]; }APP_GENERALINFO_ST; /* Stores information specific to gstreamer */ typedef struct _tag_APP_GSTINFO_ST { GstElement *pipeline; GstElement *filesrc; GstElement *demux; GstElement *videodecoder; GstElement *videobin; GstElement *videosink; GstPad *videofilterpad; GstElement *videoqueue; GstBus *bus; GMainLoop *loop; }APP_GSTINFO_ST; /*Stores all the infomation required by the application*/ typedef struct _tag_APP_INFO_ST { APP_GSTINFO_ST stAppGstInfo; APP_GENERALINFO_ST stAppGeneralInfo; }APP_INFO_ST; /*------------------------------ Function Definitions------------------------*/ /****************************************************************************** * Function : InitializeAppInfostruct * Description : Api to initialize APP_INFO_ST structure. * This will also set the width, height, filename etc. * *****************************************************************************/ void InitializeAppInfostruct(APP_INFO_ST *pstAppInfo, int cntNoofWindows) { memset(pstAppInfo, 0, sizeof(APP_INFO_ST)); pstAppInfo->stAppGeneralInfo.x = x[cntNoofWindows]; pstAppInfo->stAppGeneralInfo.y = y[cntNoofWindows]; pstAppInfo->stAppGeneralInfo.width = width[cntNoofWindows]; pstAppInfo->stAppGeneralInfo.height = height[cntNoofWindows]; strcpy(pstAppInfo->stAppGeneralInfo.currentfilename, FileName[cntNoofWindows]); return; } /****************************************************************************** * Function : CreateApp_Window * Description : Api to create window and to give the window ID * to vaapi sink. * Window ID to be created by the application only * when 'prepare-xwindow-id' message comes. ******************************************************************************/ static GstBusSyncReply CreateApp_Window(GstBus * bus, GstMessage * message, void *pvAppGeneralInfo) { APP_GENERALINFO_ST *pstAppGeneralInfo = pvAppGeneralInfo; PRINT("Message src = %s\n", gst_object_get_name(GST_MESSAGE_SRC (message))); /* Ignore all other messages except 'prepare-xwindow-id' element messages */ if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) return GST_BUS_PASS; if (!gst_structure_has_name (message->structure, "prepare-xwindow-id")) return GST_BUS_PASS; /* This is to displayable the window manager decorations i.e border, title bar etc.*/ XSetWindowAttributes stXSWAttr = {0}; int i32XWindowMask = 0; /* Background color set to black for the displayplay.*/ stXSWAttr.background_pixel = BlackPixel(display, 0); /* Set flag to tell Window manager to not intercept commands to this * window. */ stXSWAttr.override_redirect = True; /* Set mask. */ i32XWindowMask = CWBackPixel|CWBorderPixel|CWOverrideRedirect; /* Create X window */ pstAppGeneralInfo->win = XCreateWindow(display, RootWindow(display,0), pstAppGeneralInfo->x, pstAppGeneralInfo->y, pstAppGeneralInfo->width, pstAppGeneralInfo->height, 0, DefaultDepth(display,0), InputOutput, CopyFromParent, i32XWindowMask, &stXSWAttr); /*Map the contents of the window to displayplay */ XMapWindow(display, pstAppGeneralInfo->win); XFlush (display); XSync (display, False); /* Tell the sink to render on the X window ID created above */ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY (GST_MESSAGE_SRC (message)), pstAppGeneralInfo->win); gst_message_unref (message); return GST_BUS_DROP; } /****************************************************************************** * Function : bus_callback * Description : Callback api for bus to receives messages * like EOS, error etc. ******************************************************************************/ static gboolean bus_callback (GstBus *bus, GstMessage *message, void *pvAppInfo) { APP_INFO_ST *pstAppInfo = pvAppInfo; PRINT("Message src = %s", gst_object_get_name(GST_MESSAGE_SRC (message))); switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: { GError *err; gchar *debug; gst_message_parse_error (message, &err, &debug); g_print ("Error: %s\n", err->message); g_error_free (err); g_free (debug); g_main_loop_quit (pstAppInfo->stAppGstInfo.loop); break; }/* End of case GST_MESSAGE_ERROR*/ case GST_MESSAGE_EOS: { /* end-of-stream received */ PRINT("Received EOS"); /* Stop the gmain loop */ g_main_loop_quit (pstAppInfo->stAppGstInfo.loop); /* Destroy the window */ XDestroyWindow(display, pstAppInfo->stAppGeneralInfo.win); /* Set the pipeline to NULL state */ gst_element_set_state (pstAppInfo->stAppGstInfo.pipeline, GST_STATE_NULL); /* Set the pipeline to PLAYING state */ gst_element_set_state (pstAppInfo->stAppGstInfo.pipeline, GST_STATE_PLAYING); /* Create gthread again and run gmain loop */ g_thread_create ((GThreadFunc)g_main_loop_run, pstAppInfo->stAppGstInfo.loop, TRUE, NULL); break; }/* End of case GST_MESSAGE_EOS*/ default: break; }/* End of switch*/ return TRUE; } /****************************************************************************** * Function : cb_newpad * Description : Linking the demuxer pad to video bin pad. ******************************************************************************/ static void cb_newpad (GstElement *demuxbin, GstPad *pad, gpointer data) { GstCaps *caps; GstStructure *str; GstPad *videopad; gchar *tex; GstElement *trybin = (GstElement *)data; /* check media type */ caps = gst_pad_get_caps (pad); str = gst_caps_get_structure (caps, 0); tex = (gchar*)gst_structure_get_name(str); if(g_strrstr(tex,"audio")) { return; } if(g_strrstr(tex,"video")) { videopad = gst_element_get_static_pad(trybin,"sink"); if(GST_PAD_IS_LINKED(videopad)) { g_object_unref(videopad); } else { gst_pad_link(pad,videopad); g_object_unref (videopad); } return; } } /****************************************************************************** * Function : main * Description : main of the application. * ******************************************************************************/ int main (int argc, char *argv[]) { /* Variable Declaration */ gboolean ret = 0; GstStateChangeReturn State = GST_STATE_NULL; int cntNoOfWindows = 0; APP_INFO_ST stAppInfo[NOOFWINDOWS]; /* initialize GStreamer */ gst_init (NULL, NULL); display = XOpenDisplay(NULL); while(cntNoOfWindows < NOOFWINDOWS) { PRINT("APPLICATION Started -----------------------"); /* Initialize AppInfo struct */ InitializeAppInfostruct(&stAppInfo[cntNoOfWindows], cntNoOfWindows); /* Create all elements for the following pipeline */ /* filesrc ! demux ! queue ! decoder ! sink*/ stAppInfo[cntNoOfWindows].stAppGstInfo.pipeline = gst_pipeline_new ("Pipeline to play video using vaapi"); if(NULL == stAppInfo[cntNoOfWindows].stAppGstInfo.pipeline) { PRINT("ERROR : pipeline could not be created : aborting application"); return -1; } /* Create a Gmain LOOP */ stAppInfo[cntNoOfWindows].stAppGstInfo.loop = g_main_loop_new (NULL, FALSE); /* Create a Bus */ stAppInfo[cntNoOfWindows].stAppGstInfo.bus = gst_pipeline_get_bus (GST_PIPELINE (stAppInfo[cntNoOfWindows].\ stAppGstInfo.pipeline)); /* Attach a call-back to the BUS */ gst_bus_add_watch (stAppInfo[cntNoOfWindows].stAppGstInfo.bus, bus_callback, &stAppInfo[cntNoOfWindows]); /* Set sync handler to create foriegn X window */ gst_bus_set_sync_handler (stAppInfo[cntNoOfWindows].\ stAppGstInfo.bus, (GstBusSyncHandler) CreateApp_Window, &(stAppInfo[cntNoOfWindows].stAppGeneralInfo)); gst_object_unref (stAppInfo[cntNoOfWindows].stAppGstInfo.bus); stAppInfo[cntNoOfWindows].stAppGstInfo.filesrc = gst_element_factory_make ("filesrc", "file source"); if(NULL == stAppInfo[cntNoOfWindows].stAppGstInfo.filesrc) { PRINT("ERROR : Filesrc could not be created : aborting application"); return -1; } #if MPEGTS demux = gst_element_factory_make ("ffdemux_mpegts", "demux"); #endif #if MOV stAppInfo[cntNoOfWindows].stAppGstInfo.demux = gst_element_factory_make ("ffdemux_mov_mp4_m4a_3gp_3g2_mj2", "demux"); #endif if(NULL == stAppInfo[cntNoOfWindows].stAppGstInfo.demux) { PRINT("ERROR : Demuxer could not be created : aborting application"); return -1; } stAppInfo[cntNoOfWindows].stAppGstInfo.videodecoder = gst_element_factory_make ("vaapidecode", "decoder"); if(NULL == stAppInfo[cntNoOfWindows].stAppGstInfo.videodecoder) { PRINT("ERROR : Vaapi Decoder could not be created : aborting application"); return -1; } stAppInfo[cntNoOfWindows].stAppGstInfo.videosink = gst_element_factory_make ("vaapisink", "sink"); if(NULL == stAppInfo[cntNoOfWindows].stAppGstInfo.videosink) { PRINT("ERROR : Vaapi sink could not be created : aborting application"); return -1; } stAppInfo[cntNoOfWindows].stAppGstInfo.videoqueue = gst_element_factory_make ("queue", "videoqueue"); if(NULL == stAppInfo[cntNoOfWindows].stAppGstInfo.videoqueue) { PRINT("ERROR : Video Queue could not be created : aborting application"); return -1; } g_object_set (G_OBJECT (stAppInfo[cntNoOfWindows].stAppGstInfo.filesrc), "location", (unsigned char*)stAppInfo[cntNoOfWindows].stAppGeneralInfo.\ currentfilename, NULL); gst_bin_add_many (GST_BIN (stAppInfo[cntNoOfWindows].stAppGstInfo.pipeline), stAppInfo[cntNoOfWindows].stAppGstInfo.filesrc, stAppInfo[cntNoOfWindows].stAppGstInfo.demux,NULL); gst_element_link_many (stAppInfo[cntNoOfWindows].stAppGstInfo.filesrc, stAppInfo[cntNoOfWindows].stAppGstInfo.demux, NULL); /* create video bin */ stAppInfo[cntNoOfWindows].stAppGstInfo.videobin = gst_bin_new ("videobin"); gst_bin_add_many (GST_BIN (stAppInfo[cntNoOfWindows].stAppGstInfo.videobin), stAppInfo[cntNoOfWindows].stAppGstInfo.videoqueue, stAppInfo[cntNoOfWindows].stAppGstInfo.videodecoder, stAppInfo[cntNoOfWindows].stAppGstInfo.videosink, NULL); gst_bin_add(GST_BIN(stAppInfo[cntNoOfWindows].stAppGstInfo.pipeline), stAppInfo[cntNoOfWindows].stAppGstInfo.videobin); stAppInfo[cntNoOfWindows].stAppGstInfo.videofilterpad = gst_element_get_static_pad (stAppInfo[cntNoOfWindows].stAppGstInfo.videoqueue, "sink"); gst_element_add_pad (stAppInfo[cntNoOfWindows].stAppGstInfo.videobin, gst_ghost_pad_new ("sink", stAppInfo[cntNoOfWindows].stAppGstInfo.videofilterpad)); g_signal_connect (stAppInfo[cntNoOfWindows].stAppGstInfo.demux, "pad-added", G_CALLBACK (cb_newpad), stAppInfo[cntNoOfWindows].stAppGstInfo.videobin); ret = gst_element_link_many (stAppInfo[cntNoOfWindows].stAppGstInfo.videoqueue, stAppInfo[cntNoOfWindows].stAppGstInfo.videodecoder, stAppInfo[cntNoOfWindows].stAppGstInfo.videosink, NULL); if(0 == ret) { PRINT("Failed to link queue, decoder and sink"); return -1; } gst_object_unref(stAppInfo[cntNoOfWindows].stAppGstInfo.videofilterpad); /* Change the pipeline state to READY */ State = gst_element_set_state (stAppInfo[cntNoOfWindows].stAppGstInfo.pipeline, GST_STATE_READY); if(GST_STATE_CHANGE_FAILURE == State) { PRINT("State = %d", State); return 0; } /* Change the pipeline state to PLAYING */ State = gst_element_set_state (stAppInfo[cntNoOfWindows].stAppGstInfo.pipeline, GST_STATE_PLAYING); if(GST_STATE_CHANGE_FAILURE == State) { PRINT("State = %d", State); return 0; } /*Start the gmain loop by creating a gthread*/ g_thread_create ((GThreadFunc)g_main_loop_run, stAppInfo[cntNoOfWindows].stAppGstInfo.loop, FALSE, NULL); sleep(1); cntNoOfWindows++; } while(1); return 0; } /* End of application */ _______________________________________________ gstreamer-devel mailing list [hidden email] http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Free forum by Nabble | Edit this page |