Hi,

I am trying to play multiple videos simultaneously using GStreamer(vaapidecode and vaapisink plugins) and libVA-1.0.7. In the sample application I am creating multiple windows using "XCreateWindow" and passing the generated window ID to vaapisink.
There are two problems I am facing:

1. The first video is getting rendered but the other videos are not getting rendered.

2. 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.

The backtrace of the gdb log is attached "CrashLog.txt". The log suggests the crash is in "i965_PutSurface".

I am using the following packages as mentioned on Intel Linux graphics site "http://intellinuxgraphics.org/2010Q4.html":

2D driver: xf86-video-intel 2.14.0 release <http://xorg.freedesktop.org/archive/individual/driver/xf86-video-intel-2.14.0.tar.bz2>
3D driver: mesa 7.10 <ftp://freedesktop.org/pub/mesa/7.10/>
Libdrm: libdrm-2.4.23 release <http://dri.freedesktop.org/libdrm/libdrm-2.4.23.tar.bz2> Kernel: 2.6.37 release <http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.37.tar.bz2>
Cairo: cairo-1.10.2 release <http://cairographics.org/news/cairo-1.10.2/>
Libva: libva-1.0.7 release <http://cgit.freedesktop.org/libva/snapshot/libva-1.0.7.tar.bz2>
xserver: 1.9.3

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.

For reference attaching the sample application "MultiVideo.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 decoder like ffmpeg.
What could be the problem?

PS : OS : Fedora Core 13. Platform: Sandy Bridge.Kernel : 2.6.37.

Regards,
Jyotsana.

/* Back trace from 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=<value optimized 
out>, 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=<value optimized 
out>) at i965_render.c:1808
#5  gen6_render_emit_states (ctx=0xaf2bc178, kernel=<value optimized out>) 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=<value optimized out>, 
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

/* 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 codec: mp3.*/

/* 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 */

#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>


#define VIDEO_ENABLE   1
#define AUDIO_ENABLE   0   /* If the video has audio then enable this */
#define NOOFFILES      4   /* Max No of files to be played 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 */

/* Variable Declaration */

/* Display and window declaration*/
Display *dis;
Window win[NOOFFILES];

/* Elements*/
GstElement *pipeline[NOOFFILES];
GstElement *videobin[NOOFFILES] ;
GstElement *audiobin[NOOFFILES]  ;
GstElement *src[NOOFFILES]  ;
GstElement *decoder[NOOFFILES];
GstElement *sink[NOOFFILES];
GstElement *demux[NOOFFILES];
GstPad *videofilterpad[NOOFFILES];
GstPad *audiofilterpad[NOOFFILES];
GstElement *audpipeline[NOOFFILES];
GstElement *audiodec[NOOFFILES];
GstElement *audiosink[NOOFFILES];
GstElement *videoqueue[NOOFFILES];
GstElement *audioqueue[NOOFFILES];
GstElement *filter[NOOFFILES];
GstBus *bus[NOOFFILES];    
GMainLoop *loop[NOOFFILES];

char FileName[NOOFFILES][256] = {"Nature Video Clips (For Review)_1280.mov", 
"City Video Clips _1280.mov","City Video Clips _1280.mov","City Video Clips 
_1280.mov"};
volatile int EOSFlag = 0;
int cntNoOfFiles = 0;

/*Variables for setting the window location */
int x[NOOFFILES] = {0, 550, 0, 550};
int y[NOOFFILES] = {0, 0, 550 , 550};
int width[NOOFFILES] = {500, 500, 500, 500};
int height[NOOFFILES] = {500, 500, 500, 500};

/* Function definitions*/

/* Api to create window and to give the window ID to vaapi sink*/
static GstBusSyncReply
create_window(GstBus * bus, GstMessage * message, void *data)
{

  /*printf("Message src = %s\n", gst_object_get_name(GST_MESSAGE_SRC 
(message)));*/
  /* ignore anything but '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;

  static int filenumber = 0;

  /* When EOS is received reset the static var */
  if(EOSFlag == 1)
  {
    filenumber = 0;
    EOSFlag = 0;
  }

 /* This is to disable the window manager decorations i.e border, title bar 
etc.*/
  XSetWindowAttributes stXSWAttr = {0};
  int i32XWindowMask = 0;

  /* Background color set to black for the display.*/
  stXSWAttr.background_pixel = BlackPixel(dis, 0);

  /* Set flag to tell Window manager to not intercept commands to this 
   * window. */
  stXSWAttr.override_redirect = True;

  /* Set mask. */
  i32XWindowMask = CWBackPixel|CWBorderPixel|CWOverrideRedirect;

  win[filenumber] = XCreateWindow(dis,
                    RootWindow(dis,0),
                    x[filenumber],
                    y[filenumber],
                    width[filenumber],
                    height[filenumber],
                    0, DefaultDepth(dis,0),
                    InputOutput,
                    CopyFromParent,
                    i32XWindowMask,
                    &stXSWAttr);

  XMapWindow(dis, win[filenumber]);
  XFlush (dis); 
  XSync (dis, 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)), 
win[filenumber]);

  filenumber++;

  gst_message_unref (message);

  return GST_BUS_DROP;
}

/* Bus to receive messages like EOS and any error messages */
static gboolean my_bus_callback (    GstBus     *bus,
                     GstMessage *message,
                     void    *data)
{
  static int filenumber = 0;
  /*printf("Message src = %s\n", 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 (loop[filenumber]);
      break;
    }/* End of case GST_MESSAGE_ERROR*/
        
    case GST_MESSAGE_EOS:
    {
      /* end-of-stream received */
      printf("Received EOS\n");
      /* Stop the gmain loop */
      g_main_loop_quit (loop[filenumber]);

      /* Destroy the window */
      XDestroyWindow(dis, win[filenumber]);

      if(filenumber == 0)
        EOSFlag = 1;

      gst_element_set_state (pipeline[filenumber], GST_STATE_NULL);
      gst_element_set_state (pipeline[filenumber], GST_STATE_PLAYING);
      g_thread_create ((GThreadFunc)g_main_loop_run, loop[filenumber],  TRUE, 
NULL);
      filenumber++;
      /* Reset the static var*/
      if(filenumber == NOOFFILES)
        filenumber = 0;
      break;
    }/* End of case GST_MESSAGE_EOS*/

    default:
      /* unhandled message */
      break;
  }/* End of switch*/

  return TRUE;
}

/* Api to request demuxer pad and to link it the videobin/audiobin*/
static void
cb_newpad (GstElement *demuxbin,
       GstPad     *pad,
       gpointer    data)
{
  GstCaps *caps;
  GstStructure *str;
  GstPad *videopad;
  GstPad *audiopad;
  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"))
  {
    audiopad = gst_element_get_static_pad(trybin,"sink");
    if(GST_PAD_IS_LINKED(audiopad))
    {
      g_object_unref(audiopad);
    }
    else
    {
      gst_pad_link(pad,audiopad);
      g_object_unref (audiopad);
    }
    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;
  }
}

/*Main of the application */
int main (int argc, char *argv[])
{
  /* Variable Declaration */
  gboolean ret;
  GstStateChangeReturn State = GST_STATE_NULL;     

  /* initialize GStreamer */
  gst_init (NULL, NULL);

  dis = XOpenDisplay(NULL);

  while(cntNoOfFiles < NOOFFILES)
  {      
    printf("\n\n APPLICATION Started -----------------------> \n");

    /* Create all elements for the following pipeline */
    /* filesrc ! demux d.! queue ! decoder ! sink d.! queue ! audiodec ! 
audiosink*/
    pipeline[cntNoOfFiles] = gst_pipeline_new ("Pipeline to play h264 video 
from filesrc.");
    if(NULL == pipeline[cntNoOfFiles])
    {
      printf("ERROR : pipeline could not be created : aborting application \n");
      return -1;
    }
    
    /* Create a Gmain LOOP */
    loop[cntNoOfFiles] = g_main_loop_new (NULL, FALSE);

    /* Create a Bus */
    bus[cntNoOfFiles] = gst_pipeline_get_bus (GST_PIPELINE 
(pipeline[cntNoOfFiles]));

    /* Attach a call-back to the BUS */
    gst_bus_add_watch (bus[cntNoOfFiles], my_bus_callback, NULL);

    /* Set sync handler to create foriegn X window */
    gst_bus_set_sync_handler (bus[cntNoOfFiles], (GstBusSyncHandler) 
create_window, NULL);

    gst_object_unref (bus[cntNoOfFiles]);    

    src[cntNoOfFiles] = gst_element_factory_make ("filesrc", "file source");
    if(NULL == src[cntNoOfFiles])
    {
      printf("ERROR : Filesrc could not be created : aborting application \n");
      return -1;
    }

#if MPEGTS
    demux = gst_element_factory_make ("ffdemux_mpegts", "demux");
#endif
#if MOV
    demux[cntNoOfFiles] = gst_element_factory_make 
("ffdemux_mov_mp4_m4a_3gp_3g2_mj2", "demux");
#endif
    if(NULL == demux[cntNoOfFiles])
    {
      printf("ERROR : Demuxer could not be created : aborting application \n");
      return -1;
    }

    decoder[cntNoOfFiles] = gst_element_factory_make ("vaapidecode", "decoder");
    if(NULL == decoder[cntNoOfFiles])
    {
      printf("ERROR : Decoder could not be created : aborting application \n");
      return -1;
    }

    sink[cntNoOfFiles] = gst_element_factory_make ("vaapisink", "sink");
    if(NULL == sink[cntNoOfFiles])
    {
      printf("ERROR : Vaapi sink could not be created : aborting application 
\n");
      return -1;
    }

    audiodec[cntNoOfFiles] = gst_element_factory_make ("ffdec_mp3", "audiodec");
    if(NULL == audiodec[cntNoOfFiles])
    {
      printf("ERROR :Audio Decoder could not be created : aborting application 
\n");
      return -1;
    }

    audiosink[cntNoOfFiles] = gst_element_factory_make ("alsasink", "alsasink");
    if(NULL == audiosink[cntNoOfFiles])
    {
      printf("ERROR : Audio sink could not be created : aborting application 
\n");
      return -1;
    }

    audioqueue[cntNoOfFiles] = gst_element_factory_make ("queue", "audioqueue");
    if(NULL == audioqueue[cntNoOfFiles])
    {
      printf("ERROR : Audio Queue could not be created : aborting application 
\n");
      return -1;
    }

    videoqueue[cntNoOfFiles] = gst_element_factory_make ("queue", "videoqueue");
    if(NULL == videoqueue[cntNoOfFiles])
    {
      printf("ERROR : Video Queue could not be created : aborting application 
\n");
      return -1;
    }

    g_object_set (G_OBJECT (src[cntNoOfFiles]), "location", (unsigned 
char*)FileName[cntNoOfFiles], NULL);
    gst_bin_add_many (GST_BIN (pipeline[cntNoOfFiles]), src[cntNoOfFiles], 
demux[cntNoOfFiles],NULL);
    gst_element_link_many (src[cntNoOfFiles], demux[cntNoOfFiles], NULL);

#if VIDEO_ENABLE
    /* create video bin */
    videobin[cntNoOfFiles] = gst_bin_new ("videobin");

    gst_bin_add_many (GST_BIN (videobin[cntNoOfFiles]), 
    videoqueue[cntNoOfFiles],
    decoder[cntNoOfFiles],
    sink[cntNoOfFiles], NULL);
    gst_bin_add(GST_BIN(pipeline[cntNoOfFiles]), videobin[cntNoOfFiles]);

    videofilterpad[cntNoOfFiles] = gst_element_get_static_pad 
(videoqueue[cntNoOfFiles], "sink");
    gst_element_add_pad (videobin[cntNoOfFiles], gst_ghost_pad_new ("sink", 
videofilterpad[cntNoOfFiles]));
    g_signal_connect (demux[cntNoOfFiles], "pad-added", G_CALLBACK (cb_newpad), 
videobin[cntNoOfFiles]);

    ret = gst_element_link_many (videoqueue[cntNoOfFiles],
                                 decoder[cntNoOfFiles], 
                                 sink[cntNoOfFiles], NULL);

    if(0 == ret)
    {
      printf("Failed to link queue decoder and sink.\n");
      return -1;
    }
    gst_object_unref(videofilterpad[cntNoOfFiles]);
    
#endif

#if AUDIO_ENABLE
    /* create audio bin */
    audiobin[cntNoOfFiles] = gst_bin_new ("audiobin");

    gst_bin_add_many (GST_BIN (audiobin[cntNoOfFiles]), 
audioqueue[cntNoOfFiles],audiodec[cntNoOfFiles],audiosink[cntNoOfFiles], NULL);
    gst_bin_add(GST_BIN(pipeline[cntNoOfFiles]), audiobin[cntNoOfFiles]);

    audiofilterpad[cntNoOfFiles] = gst_element_get_static_pad 
(audioqueue[cntNoOfFiles], "sink");
    gst_element_add_pad (audiobin[cntNoOfFiles], gst_ghost_pad_new ("sink", 
audiofilterpad[cntNoOfFiles]));
    g_signal_connect (demux[cntNoOfFiles], "pad-added", G_CALLBACK (cb_newpad), 
audiobin[cntNoOfFiles]);

    ret = gst_element_link_many 
(audioqueue[cntNoOfFiles],audiodec[cntNoOfFiles], audiosink[cntNoOfFiles], 
NULL);
    if(0 == ret)
    {
      printf("Failed to link queue decoder and sink.\n");
      return -1;
    }
    gst_object_unref(audiofilterpad[cntNoOfFiles]);

#endif

    /* Change the pipeline state to READY */
    State = gst_element_set_state (pipeline[cntNoOfFiles], GST_STATE_READY);
    if(GST_STATE_CHANGE_FAILURE == State) 
    {
      printf("State = %d.\n", State);
      return 0;
    }
    
    /* Change the pipeline state to PLAYING */
    printf("\npipeline 1 :   PLAYING  ................................. \n");
    State = gst_element_set_state (pipeline[cntNoOfFiles], GST_STATE_PLAYING);
    if(GST_STATE_CHANGE_FAILURE == State) 
    {
      printf("State = %d.\n", State);
      return 0;
    }
    
    /*Start the gmain loop by creating a gthread*/
    g_thread_create ((GThreadFunc)g_main_loop_run, loop[cntNoOfFiles],  FALSE, 
NULL);         
 
    sleep(1);
    cntNoOfFiles++;
  }
      
  while(1);

  return 0;

}

/* End of application */

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to