emotion: make gstreamer backend async and handle it correctly every where.
authorcedric <cedric>
Tue, 2 Aug 2011 16:22:30 +0000 (16:22 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 2 Aug 2011 16:22:30 +0000 (16:22 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/emotion@62010 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/emotion_smart.c
src/modules/gstreamer/emotion_gstreamer.c
src/modules/gstreamer/emotion_gstreamer.h
src/modules/gstreamer/emotion_sink.c

index 986e3d1..7217103 100644 (file)
@@ -82,6 +82,7 @@ struct _Smart_Data
 
    double         ratio;
    double         pos;
+   double         remember_jump;
    double         seek_pos;
    double         len;
 
@@ -89,7 +90,9 @@ struct _Smart_Data
 
    Emotion_Suspend state;
 
+   Eina_Bool open : 1;
    Eina_Bool play : 1;
+   Eina_Bool remember_play : 1;
    Eina_Bool seek : 1;
    Eina_Bool seeking : 1;
 };
@@ -329,8 +332,10 @@ emotion_object_init(Evas_Object *obj, const char *module_filename)
    sd->spu.button = -1;
    sd->ratio = 1.0;
    sd->pos = 0;
+   sd->remember_jump = 0;
    sd->seek_pos = 0;
    sd->len = 0;
+   sd->remember_play = 0;
 
    _emotion_module_close(sd->module, sd->video);
    sd->module = NULL;
@@ -370,6 +375,7 @@ emotion_object_file_set(Evas_Object *obj, const char *file)
        sd->module->file_close(sd->video);
         evas_object_image_data_set(sd->obj, NULL);
        evas_object_image_size_set(sd->obj, 1, 1);
+        sd->open = 0;
        if (!sd->module->file_open(sd->file, obj, sd->video))
          return EINA_FALSE;
        sd->module->size_get(sd->video, &w, &h);
@@ -419,7 +425,13 @@ emotion_object_play_set(Evas_Object *obj, Eina_Bool play)
    if (play == sd->play) return;
    if (!sd->module) return;
    if (!sd->video) return;
+   if (!sd->open)
+     {
+        sd->remember_play = play;
+        return;
+     }
    sd->play = play;
+   sd->remember_play = play;
    if (sd->state != EMOTION_WAKEUP) emotion_object_suspend_set(obj, EMOTION_WAKEUP);
    if (sd->play) sd->module->play(sd->video, sd->pos);
    else sd->module->stop(sd->video);
@@ -445,6 +457,12 @@ emotion_object_position_set(Evas_Object *obj, double sec)
    DBG("sec=%f", sec);
    if (!sd->module) return;
    if (!sd->video) return;
+   if (!sd->open)
+     {
+        sd->remember_jump = sec;
+        return ;
+     }
+   sd->remember_jump = 0;
    sd->seek_pos = sec;
    sd->seek = 1;
    sd->pos = sd->seek_pos;
@@ -1064,7 +1082,11 @@ emotion_object_last_position_load(Evas_Object *obj)
 
    EINA_REFCOUNT_REF(sd);
 
-   sd->load_xattr = eio_file_xattr_get(tmp, "user.e.time_seek", _eio_load_xattr_done, _eio_load_xattr_error, sd);
+   sd->load_xattr = eio_file_xattr_get(tmp,
+                                       "user.e.time_seek",
+                                       _eio_load_xattr_done,
+                                       _eio_load_xattr_error,
+                                       sd);
 #else
 # ifdef HAVE_XATTR
    {
@@ -1266,6 +1288,15 @@ _emotion_decode_stop(Evas_Object *obj)
 EAPI void
 _emotion_open_done(Evas_Object *obj)
 {
+   Smart_Data *sd;
+
+   E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+   sd->open = 1;
+
+   if (sd->remember_jump)
+     emotion_object_position_set(obj, sd->remember_jump);
+   if (sd->remember_play != sd->play)
+     emotion_object_play_set(obj, sd->remember_play);
    evas_object_smart_callback_call(obj, SIG_OPEN_DONE, NULL);
 }
 
index e58532b..cf22e3d 100644 (file)
@@ -355,6 +355,12 @@ em_shutdown(void *video)
    if (!ev)
      return 0;
 
+   if (ev->thread)
+     {
+        ecore_thread_cancel(ev->thread);
+        ev->thread = NULL;
+     }
+
    if (ev->pipeline)
      {
        gst_element_set_state(ev->pipeline, GST_STATE_NULL);
@@ -381,8 +387,6 @@ em_file_open(const char   *file,
    Emotion_Gstreamer_Video *ev;
    Eina_Strbuf *sbuf = NULL;
    const char *uri;
-   double start, end;
-   int i;
 
    ev = (Emotion_Gstreamer_Video *)video;
 
@@ -410,28 +414,20 @@ em_file_open(const char   *file,
         eina_strbuf_append(sbuf, file);
      }
 
-   start = ecore_time_get();
    uri = sbuf ? eina_strbuf_string_get(sbuf) : file;
    DBG("setting file to '%s'", uri);
    ev->pipeline = gstreamer_video_sink_new(ev, obj, uri);
    if (sbuf) eina_strbuf_free(sbuf);
-   end = ecore_time_get();
-   DBG("Pipeline creation: %f", end - start);
 
    if (!ev->pipeline)
      return EINA_FALSE;
 
-   eina_threads_init();
-
-   start = ecore_time_get();
    ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline));
    if (!ev->eos_bus)
      {
         ERR("could not get the bus");
         return EINA_FALSE;
      }
-   end = ecore_time_get();
-   DBG("Get the bus: %f", end - start);
 
    gst_bus_set_sync_handler(ev->eos_bus, _eos_sync_fct, ev);
 
@@ -440,258 +436,6 @@ em_file_open(const char   *file,
 
    ev->position = 0.0;
 
-   g_object_get(G_OBJECT(ev->pipeline),
-                "n-audio", &ev->audio_stream_nbr,
-                "n-video", &ev->video_stream_nbr,
-                NULL);
-
-   if ((ev->video_stream_nbr == 0) && (ev->audio_stream_nbr == 0))
-     {
-        ERR("No audio nor video stream found");
-        gst_object_unref(ev->pipeline);
-        ev->pipeline = NULL;
-        return EINA_FALSE;
-     }
-
-   /* video stream */
-
-   start = ecore_time_get();
-   for (i = 0; i < ev->video_stream_nbr; i++)
-     {
-        Emotion_Video_Stream *vstream;
-        GstPad       *pad = NULL;
-        GstCaps      *caps;
-        GstStructure *structure;
-        GstQuery     *query;
-        const GValue *val;
-        gchar        *str;
-
-        gdouble length_time = 0.0;
-        gint width;
-        gint height;
-        gint fps_num;
-        gint fps_den;
-        guint32 fourcc = 0;
-
-        g_signal_emit_by_name(ev->pipeline, "get-video-pad", i, &pad);
-        if (!pad)
-          continue;
-
-        caps = gst_pad_get_negotiated_caps(pad);
-        if (!caps)
-          goto unref_pad_v;
-        structure = gst_caps_get_structure(caps, 0);
-        str = gst_caps_to_string(caps);
-
-        if (!gst_structure_get_int(structure, "width", &width))
-          goto unref_caps_v;
-        if (!gst_structure_get_int(structure, "height", &height))
-          goto unref_caps_v;
-        if (!gst_structure_get_fraction(structure, "framerate", &fps_num, &fps_den))
-          goto unref_caps_v;
-
-        if (g_str_has_prefix(str, "video/x-raw-yuv"))
-          {
-             val = gst_structure_get_value(structure, "format");
-             fourcc = gst_value_get_fourcc(val);
-          }
-        else if (g_str_has_prefix(str, "video/x-raw-rgb"))
-          fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
-        else
-          goto unref_caps_v;
-
-        query = gst_query_new_duration(GST_FORMAT_TIME);
-        if (gst_pad_peer_query(pad, query))
-          {
-             gint64 t;
-
-             gst_query_parse_duration(query, NULL, &t);
-             length_time = (double)t / (double)GST_SECOND;
-          }
-        else
-          goto unref_query_v;
-
-        vstream = emotion_video_stream_new(ev);
-        if (!vstream) goto unref_query_v;
-
-        vstream->length_time = length_time;
-        vstream->width = width;
-        vstream->height = height;
-        vstream->fps_num = fps_num;
-        vstream->fps_den = fps_den;
-        vstream->fourcc = fourcc;
-        vstream->index = i;
-
-     unref_query_v:
-        gst_query_unref(query);
-     unref_caps_v:
-        gst_caps_unref(caps);
-     unref_pad_v:
-        gst_object_unref(pad);
-     }
-   end = ecore_time_get();
-   DBG("Get video streams: %f", end - start);
-
-   /* Audio streams */
-
-   start = ecore_time_get();
-   for (i = 0; i < ev->audio_stream_nbr; i++)
-     {
-        Emotion_Audio_Stream *astream;
-        GstPad       *pad;
-        GstCaps      *caps;
-        GstStructure *structure;
-        GstQuery     *query;
-
-        gdouble length_time = 0.0;
-        gint channels;
-        gint samplerate;
-
-        g_signal_emit_by_name(ev->pipeline, "get-audio-pad", i, &pad);
-        if (!pad)
-          continue;
-
-        caps = gst_pad_get_negotiated_caps(pad);
-        if (!caps)
-          goto unref_pad_a;
-        structure = gst_caps_get_structure(caps, 0);
-
-        if (!gst_structure_get_int(structure, "channels", &channels))
-          goto unref_caps_a;
-        if (!gst_structure_get_int(structure, "rate", &samplerate))
-          goto unref_caps_a;
-
-        query = gst_query_new_duration(GST_FORMAT_TIME);
-        if (gst_pad_peer_query(pad, query))
-          {
-             gint64 t;
-
-             gst_query_parse_duration(query, NULL, &t);
-             length_time = (double)t / (double)GST_SECOND;
-          }
-        else
-          goto unref_query_a;
-
-        astream = calloc(1, sizeof(Emotion_Audio_Stream));
-        if (!astream) continue;
-        ev->audio_streams = eina_list_append(ev->audio_streams, astream);
-        if (eina_error_get())
-          {
-             free(astream);
-             continue;
-          }
-
-        astream->length_time = length_time;
-        astream->channels = channels;
-        astream->samplerate = samplerate;
-
-     unref_query_a:
-        gst_query_unref(query);
-     unref_caps_a:
-        gst_caps_unref(caps);
-     unref_pad_a:
-        gst_object_unref(pad);
-     }
-   end = ecore_time_get();
-   DBG("Get audio streams: %f", end - start);
-
-   /* Visualization sink */
-
-   start = ecore_time_get();
-   if (ev->video_stream_nbr == 0)
-     {
-        GstElement *vis = NULL;
-        Emotion_Video_Stream *vstream;
-        Emotion_Audio_Stream *astream;
-        gint flags;
-        const char *vis_name;
-
-        if (!(vis_name = emotion_visualization_element_name_get(ev->vis)))
-          {
-             WRN("pb vis name %d", ev->vis);
-             goto finalize;
-          }
-
-        astream = eina_list_data_get(ev->audio_streams);
-
-        vis = gst_element_factory_make(vis_name, "vissink");
-        vstream = emotion_video_stream_new(ev);
-        if (!vstream)
-          goto finalize;
-        else
-          DBG("could not create visualization stream");
-
-        vstream->length_time = astream->length_time;
-        vstream->width = 320;
-        vstream->height = 200;
-        vstream->fps_num = 25;
-        vstream->fps_den = 1;
-        vstream->fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
-
-        g_object_set(G_OBJECT(ev->pipeline), "vis-plugin", vis, NULL);
-        g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL);
-        flags |= 0x00000008;
-        g_object_set(G_OBJECT(ev->pipeline), "flags", flags, NULL);
-     }
-   end = ecore_time_get();
-   DBG("Get visualization streams: %f", end - start);
-
- finalize:
-
-   ev->video_stream_nbr = eina_list_count(ev->video_streams);
-   ev->audio_stream_nbr = eina_list_count(ev->audio_streams);
-
-   if (ev->video_stream_nbr == 1)
-     {
-       Emotion_Video_Stream *vstream;
-
-       vstream = eina_list_data_get(ev->video_streams);
-       ev->ratio = (double)vstream->width / (double)vstream->height;
-       _emotion_frame_resize(ev->obj, vstream->width, vstream->height, ev->ratio);
-     }
-
-   {
-     /* on recapitule : */
-     Emotion_Video_Stream *vstream;
-     Emotion_Audio_Stream *astream;
-
-     vstream = eina_list_data_get(ev->video_streams);
-     if (vstream)
-       {
-         DBG("video size=%dx%d, fps=%d/%d, "
-             "fourcc=%"GST_FOURCC_FORMAT", length=%"GST_TIME_FORMAT,
-             vstream->width, vstream->height, vstream->fps_num, vstream->fps_den,
-             GST_FOURCC_ARGS(vstream->fourcc),
-             GST_TIME_ARGS((guint64)(vstream->length_time * GST_SECOND)));
-       }
-
-     astream = eina_list_data_get(ev->audio_streams);
-     if (astream)
-       {
-         DBG("audio channels=%d, rate=%d, length=%"GST_TIME_FORMAT,
-             astream->channels, astream->samplerate,
-             GST_TIME_ARGS((guint64)(astream->length_time * GST_SECOND)));
-       }
-   }
-
-   if (ev->metadata)
-     _free_metadata(ev->metadata);
-   ev->metadata = calloc(1, sizeof(Emotion_Gstreamer_Metadata));
-
-   start = ecore_time_get();
-   em_audio_channel_volume_set(ev, ev->volume);
-   em_audio_channel_mute_set(ev, ev->audio_mute);
-
-   if (ev->play_started)
-     {
-        _emotion_playback_started(ev->obj);
-        ev->play_started = 0;
-     }
-
-   _emotion_open_done(ev->obj);
-   end = ecore_time_get();
-   DBG("Last stuff: %f", end - start);
-
    return 1;
 }
 
@@ -712,6 +456,12 @@ em_file_close(void *video)
         ev->eos_bus = NULL;
      }
 
+   if (ev->thread)
+     {
+        ecore_thread_cancel(ev->thread);
+        ev->thread = NULL;
+     }
+
    if (ev->pipeline)
      {
         gst_element_set_state(ev->pipeline, GST_STATE_NULL);
@@ -719,13 +469,12 @@ em_file_close(void *video)
         ev->pipeline = NULL;
      }
 
-   eina_threads_shutdown();
-
    /* we clear the stream lists */
    EINA_LIST_FREE(ev->audio_streams, astream)
      free(astream);
    EINA_LIST_FREE(ev->video_streams, vstream)
      free(vstream);
+   ev->pipeline_parsed = EINA_FALSE;
 
    /* shutdown eos */
    if (ev->metadata)
@@ -772,17 +521,21 @@ em_size_get(void  *video,
 
    ev = (Emotion_Gstreamer_Video *)video;
 
-   vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
+   if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
+     goto on_error;
+
+   vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
    if (vstream)
      {
         if (width) *width = vstream->width;
         if (height) *height = vstream->height;
+
+        return ;
      }
-   else
-     {
-        if (width) *width = 0;
-        if (height) *height = 0;
-     }
+
+ on_error:
+   if (width) *width = 0;
+   if (height) *height = 0;
 }
 
 static void
@@ -833,7 +586,7 @@ em_len_get(void *video)
    if (fmt != GST_FORMAT_TIME)
      {
         DBG("requrested duration in time, but got %s instead.",
-                gst_format_get_name(fmt));
+            gst_format_get_name(fmt));
         goto fallback;
      }
 
@@ -843,6 +596,9 @@ em_len_get(void *video)
    return val / 1000000000.0;
 
  fallback:
+   if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
+     return 0.0;
+
    EINA_LIST_FOREACH(ev->audio_streams, l, astream)
      if (astream->length_time >= 0)
        return astream->length_time;
@@ -862,7 +618,10 @@ em_fps_num_get(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
-   vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
+   if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
+     return 0;
+
+   vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
    if (vstream)
      return vstream->fps_num;
 
@@ -877,7 +636,10 @@ em_fps_den_get(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
-   vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
+   if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
+     return 1;
+
+   vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
    if (vstream)
      return vstream->fps_den;
 
@@ -892,7 +654,10 @@ em_fps_get(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
-   vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
+   if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
+     return 0.0;
+
+   vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
    if (vstream)
      return (double)vstream->fps_num / (double)vstream->fps_den;
 
@@ -986,6 +751,8 @@ em_video_handled(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
+   _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
    if (!eina_list_count(ev->video_streams))
      return 0;
 
@@ -999,6 +766,8 @@ em_audio_handled(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
+   _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
    if (!eina_list_count(ev->audio_streams))
      return 0;
 
@@ -1020,11 +789,14 @@ static Emotion_Format
 em_format_get(void *video)
 {
    Emotion_Gstreamer_Video *ev;
-   Emotion_Video_Stream      *vstream;
+   Emotion_Video_Stream    *vstream;
 
    ev = (Emotion_Gstreamer_Video *)video;
 
-   vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
+   if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
+     return EMOTION_FORMAT_NONE;
+
+   vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
    if (vstream)
      {
         switch (vstream->fourcc)
@@ -1048,21 +820,25 @@ static void
 em_video_data_size_get(void *video, int *w, int *h)
 {
    Emotion_Gstreamer_Video *ev;
-   Emotion_Video_Stream      *vstream;
+   Emotion_Video_Stream    *vstream;
 
    ev = (Emotion_Gstreamer_Video *)video;
 
-   vstream = (Emotion_Video_Stream *)eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
+   if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
+     goto on_error;
+
+   vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
    if (vstream)
      {
         *w = vstream->width;
         *h = vstream->height;
+
+        return ;
      }
-   else
-     {
-        *w = 0;
-        *h = 0;
-     }
+
+ on_error:
+   *w = 0;
+   *h = 0;
 }
 
 static int
@@ -1105,6 +881,8 @@ em_video_channel_count(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
+   _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
    return eina_list_count(ev->video_streams);
 }
 
@@ -1129,6 +907,8 @@ em_video_channel_get(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
+   _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
    return ev->video_stream_nbr;
 }
 
@@ -1169,6 +949,8 @@ em_audio_channel_count(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
+   _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
    return eina_list_count(ev->audio_streams);
 }
 
@@ -1193,6 +975,8 @@ em_audio_channel_get(void *video)
 
    ev = (Emotion_Gstreamer_Video *)video;
 
+   _emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
+
    return ev->audio_stream_nbr;
 }
 
@@ -1688,3 +1472,276 @@ _eos_sync_fct(GstBus *bus, GstMessage *msg, gpointer data)
 
    return GST_BUS_DROP;
 }
+
+Eina_Bool
+_emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev,
+                                        Eina_Bool force)
+{
+   gboolean res;
+   int i;
+
+   if (ev->pipeline_parsed)
+     return EINA_TRUE;
+
+   if (force && ev->thread)
+     {
+        ecore_thread_cancel(ev->thread);
+        ev->thread = NULL;
+     }
+
+   if (ev->thread)
+     return EINA_FALSE;
+
+   res = gst_element_get_state(ev->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
+   if (!(res == GST_STATE_CHANGE_SUCCESS
+         || res == GST_STATE_CHANGE_NO_PREROLL))
+     {
+        /** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */
+        /** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */
+        if (getenv("EMOTION_GSTREAMER_DOT"))
+          GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(ev->pipeline),
+                                            GST_DEBUG_GRAPH_SHOW_ALL,
+                                            getenv("EMOTION_GSTREAMER_DOT"));
+
+        ERR("Unable to get GST_CLOCK_TIME_NONE.");
+        return EINA_FALSE;
+     }
+
+   g_object_get(G_OBJECT(ev->pipeline),
+                "n-audio", &ev->audio_stream_nbr,
+                "n-video", &ev->video_stream_nbr,
+                NULL);
+
+   if ((ev->video_stream_nbr == 0) && (ev->audio_stream_nbr == 0))
+     {
+        ERR("No audio nor video stream found");
+        return EINA_FALSE;
+     }
+
+   /* video stream */
+   for (i = 0; i < ev->video_stream_nbr; i++)
+     {
+        Emotion_Video_Stream *vstream;
+        GstPad       *pad = NULL;
+        GstCaps      *caps;
+        GstStructure *structure;
+        GstQuery     *query;
+        const GValue *val;
+        gchar        *str;
+
+        gdouble length_time = 0.0;
+        gint width;
+        gint height;
+        gint fps_num;
+        gint fps_den;
+        guint32 fourcc = 0;
+
+        g_signal_emit_by_name(ev->pipeline, "get-video-pad", i, &pad);
+        if (!pad)
+          continue;
+
+        caps = gst_pad_get_negotiated_caps(pad);
+        if (!caps)
+          goto unref_pad_v;
+        structure = gst_caps_get_structure(caps, 0);
+        str = gst_caps_to_string(caps);
+
+        if (!gst_structure_get_int(structure, "width", &width))
+          goto unref_caps_v;
+        if (!gst_structure_get_int(structure, "height", &height))
+          goto unref_caps_v;
+        if (!gst_structure_get_fraction(structure, "framerate", &fps_num, &fps_den))
+          goto unref_caps_v;
+
+        if (g_str_has_prefix(str, "video/x-raw-yuv"))
+          {
+             val = gst_structure_get_value(structure, "format");
+             fourcc = gst_value_get_fourcc(val);
+          }
+        else if (g_str_has_prefix(str, "video/x-raw-rgb"))
+          fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
+        else
+          goto unref_caps_v;
+
+        query = gst_query_new_duration(GST_FORMAT_TIME);
+        if (gst_pad_peer_query(pad, query))
+          {
+             gint64 t;
+
+             gst_query_parse_duration(query, NULL, &t);
+             length_time = (double)t / (double)GST_SECOND;
+          }
+        else
+          goto unref_query_v;
+
+        vstream = emotion_video_stream_new(ev);
+        if (!vstream) goto unref_query_v;
+
+        vstream->length_time = length_time;
+        vstream->width = width;
+        vstream->height = height;
+        vstream->fps_num = fps_num;
+        vstream->fps_den = fps_den;
+        vstream->fourcc = fourcc;
+        vstream->index = i;
+
+     unref_query_v:
+        gst_query_unref(query);
+     unref_caps_v:
+        gst_caps_unref(caps);
+     unref_pad_v:
+        gst_object_unref(pad);
+     }
+
+   /* Audio streams */
+   for (i = 0; i < ev->audio_stream_nbr; i++)
+     {
+        Emotion_Audio_Stream *astream;
+        GstPad       *pad;
+        GstCaps      *caps;
+        GstStructure *structure;
+        GstQuery     *query;
+
+        gdouble length_time = 0.0;
+        gint channels;
+        gint samplerate;
+
+        g_signal_emit_by_name(ev->pipeline, "get-audio-pad", i, &pad);
+        if (!pad)
+          continue;
+
+        caps = gst_pad_get_negotiated_caps(pad);
+        if (!caps)
+          goto unref_pad_a;
+        structure = gst_caps_get_structure(caps, 0);
+
+        if (!gst_structure_get_int(structure, "channels", &channels))
+          goto unref_caps_a;
+        if (!gst_structure_get_int(structure, "rate", &samplerate))
+          goto unref_caps_a;
+
+        query = gst_query_new_duration(GST_FORMAT_TIME);
+        if (gst_pad_peer_query(pad, query))
+          {
+             gint64 t;
+
+             gst_query_parse_duration(query, NULL, &t);
+             length_time = (double)t / (double)GST_SECOND;
+          }
+        else
+          goto unref_query_a;
+
+        astream = calloc(1, sizeof(Emotion_Audio_Stream));
+        if (!astream) continue;
+        ev->audio_streams = eina_list_append(ev->audio_streams, astream);
+        if (eina_error_get())
+          {
+             free(astream);
+             continue;
+          }
+
+        astream->length_time = length_time;
+        astream->channels = channels;
+        astream->samplerate = samplerate;
+
+     unref_query_a:
+        gst_query_unref(query);
+     unref_caps_a:
+        gst_caps_unref(caps);
+     unref_pad_a:
+        gst_object_unref(pad);
+     }
+
+   /* Visualization sink */
+   if (ev->video_stream_nbr == 0)
+     {
+        GstElement *vis = NULL;
+        Emotion_Video_Stream *vstream;
+        Emotion_Audio_Stream *astream;
+        gint flags;
+        const char *vis_name;
+
+        if (!(vis_name = emotion_visualization_element_name_get(ev->vis)))
+          {
+             WRN("pb vis name %d", ev->vis);
+             goto finalize;
+          }
+
+        astream = eina_list_data_get(ev->audio_streams);
+
+        vis = gst_element_factory_make(vis_name, "vissink");
+        vstream = emotion_video_stream_new(ev);
+        if (!vstream)
+          goto finalize;
+        else
+          DBG("could not create visualization stream");
+
+        vstream->length_time = astream->length_time;
+        vstream->width = 320;
+        vstream->height = 200;
+        vstream->fps_num = 25;
+        vstream->fps_den = 1;
+        vstream->fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
+
+        g_object_set(G_OBJECT(ev->pipeline), "vis-plugin", vis, NULL);
+        g_object_get(G_OBJECT(ev->pipeline), "flags", &flags, NULL);
+        flags |= 0x00000008;
+        g_object_set(G_OBJECT(ev->pipeline), "flags", flags, NULL);
+     }
+
+ finalize:
+
+   ev->video_stream_nbr = eina_list_count(ev->video_streams);
+   ev->audio_stream_nbr = eina_list_count(ev->audio_streams);
+
+   if (ev->video_stream_nbr == 1)
+     {
+       Emotion_Video_Stream *vstream;
+
+       vstream = eina_list_data_get(ev->video_streams);
+       ev->ratio = (double)vstream->width / (double)vstream->height;
+       _emotion_frame_resize(ev->obj, vstream->width, vstream->height, ev->ratio);
+     }
+
+   {
+     /* on recapitule : */
+     Emotion_Video_Stream *vstream;
+     Emotion_Audio_Stream *astream;
+
+     vstream = eina_list_data_get(ev->video_streams);
+     if (vstream)
+       {
+         DBG("video size=%dx%d, fps=%d/%d, "
+             "fourcc=%"GST_FOURCC_FORMAT", length=%"GST_TIME_FORMAT,
+             vstream->width, vstream->height, vstream->fps_num, vstream->fps_den,
+             GST_FOURCC_ARGS(vstream->fourcc),
+             GST_TIME_ARGS((guint64)(vstream->length_time * GST_SECOND)));
+       }
+
+     astream = eina_list_data_get(ev->audio_streams);
+     if (astream)
+       {
+         DBG("audio channels=%d, rate=%d, length=%"GST_TIME_FORMAT,
+             astream->channels, astream->samplerate,
+             GST_TIME_ARGS((guint64)(astream->length_time * GST_SECOND)));
+       }
+   }
+
+   if (ev->metadata)
+     _free_metadata(ev->metadata);
+   ev->metadata = calloc(1, sizeof(Emotion_Gstreamer_Metadata));
+
+   em_audio_channel_volume_set(ev, ev->volume);
+   em_audio_channel_mute_set(ev, ev->audio_mute);
+
+   if (ev->play_started)
+     {
+        _emotion_playback_started(ev->obj);
+        ev->play_started = 0;
+     }
+
+   _emotion_open_done(ev->obj);
+   ev->pipeline_parsed = EINA_TRUE;
+
+   return EINA_TRUE;
+}
index bab3306..40b2e5e 100644 (file)
@@ -59,6 +59,7 @@ struct _Emotion_Gstreamer_Video
 {
    /* Gstreamer elements */
    GstElement       *pipeline;
+   Ecore_Thread     *thread;
 
    /* eos */
    GstBus           *eos_bus;
@@ -85,10 +86,11 @@ struct _Emotion_Gstreamer_Video
 
    Emotion_Vis       vis;
 
-   unsigned char     play         : 1;
-   unsigned char     play_started : 1;
-   unsigned char     video_mute   : 1;
-   unsigned char     audio_mute   : 1;
+   Eina_Bool         play         : 1;
+   Eina_Bool         play_started : 1;
+   Eina_Bool         video_mute   : 1;
+   Eina_Bool         audio_mute   : 1;
+   Eina_Bool         pipeline_parsed : 1;
 };
 
 struct _EvasVideoSink {
@@ -188,5 +190,7 @@ void emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send);
 Emotion_Gstreamer_Message *emotion_gstreamer_message_alloc(Emotion_Gstreamer_Video *ev,
                                                            GstMessage *msg);
 void emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send);
+Eina_Bool _emotion_gstreamer_video_pipeline_parse(Emotion_Gstreamer_Video *ev,
+                                                  Eina_Bool force);
 
 #endif /* __EMOTION_GSTREAMER_H__ */
index 4033349..b207844 100644 (file)
@@ -341,6 +341,11 @@ static void evas_video_sink_main_render(void *data)
    gst_data = GST_BUFFER_DATA(buffer);
    if (!gst_data) goto exit_point;
 
+   ev = evas_object_data_get(priv->o, "_emotion_gstreamer_video");
+   if (!ev) goto exit_point;
+
+   _emotion_gstreamer_video_pipeline_parse(ev, EINA_TRUE);
+
    // This prevent a race condition when data are still in the pipe
    // but the buffer size as changed because of a request from
    // emotion smart (like on a file set).
@@ -348,9 +353,6 @@ static void evas_video_sink_main_render(void *data)
    if (w != priv->width || h != priv->height)
      goto exit_point;
 
-   ev = evas_object_data_get(priv->o, "_emotion_gstreamer_video");
-   if (!ev) goto exit_point;
-
    evas_object_image_size_set(priv->o, priv->width, priv->height);
    evas_object_image_alpha_set(priv->o, 0);
    evas_object_image_colorspace_set(priv->o, priv->eformat);
@@ -619,6 +621,29 @@ gstreamer_plugin_init (GstPlugin * plugin)
                                 EVAS_TYPE_VIDEO_SINK);
 }
 
+static void
+_emotion_gstreamer_pause(void *data, Ecore_Thread *thread __UNUSED__)
+{
+   Emotion_Gstreamer_Video *ev = data;
+
+   gst_element_set_state(ev->pipeline, GST_STATE_PAUSED);
+}
+
+static void
+_emotion_gstreamer_cancel(void *data, Ecore_Thread *thread __UNUSED__)
+{
+   Emotion_Gstreamer_Video *ev = data;
+
+   ev->thread = NULL;
+}
+
+static void
+_emotion_gstreamer_end(void *data, Ecore_Thread *thread)
+{
+   _emotion_gstreamer_video_pipeline_parse(data, EINA_TRUE);
+   _emotion_gstreamer_cancel(data, thread);
+}
+
 GstElement *
 gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
                         Evas_Object *o,
@@ -628,7 +653,6 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
    GstElement *sink;
    Evas_Object *obj;
    GstStateChangeReturn res;
-   double start, end;
 
    obj = _emotion_image_get(o);
    if (!obj)
@@ -637,17 +661,13 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
         return NULL;
      }
 
-   start = ecore_time_get();
    playbin = gst_element_factory_make("playbin2", "playbin");
    if (!playbin)
      {
         ERR("Unable to create 'playbin' GstElement.");
         return NULL;
      }
-   end = ecore_time_get();
-   DBG("Playbin2: %f", end - start);
 
-   start = ecore_time_get();
    sink = gst_element_factory_make("emotion-sink", "sink");
    if (!sink)
      {
@@ -659,34 +679,11 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
    g_object_set(G_OBJECT(playbin), "uri", uri, NULL);
    g_object_set(G_OBJECT(sink), "evas-object", obj, NULL);
 
-   end = ecore_time_get();
-
-   DBG("emotion-sink: %f", end - start);
-
-   start = ecore_time_get();
-   /* res = gst_element_set_state(playbin, GST_STATE_PLAYING); */
-   res = gst_element_set_state(playbin, GST_STATE_PAUSED);
-   if (res == GST_STATE_CHANGE_FAILURE)
-     {
-        ERR("Unable to set GST_STATE_PAUSED.");
-        goto unref_pipeline;
-     }
-   end = ecore_time_get();
-   DBG("Pause pipeline: %f", end - start);
-
-   start = ecore_time_get();
-   res = gst_element_get_state(playbin, NULL, NULL, GST_CLOCK_TIME_NONE);
-   if (res != GST_STATE_CHANGE_SUCCESS)
-     {
-        /** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */
-        /** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */
-        if (getenv("EMOTION_GSTREAMER_DOT")) GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(playbin), GST_DEBUG_GRAPH_SHOW_ALL, getenv("EMOTION_GSTREAMER_DOT"));
-
-        ERR("Unable to get GST_CLOCK_TIME_NONE.");
-        goto unref_pipeline;
-     }
-   end = ecore_time_get();
-   DBG("No time: %f", end - start);
+   ev->pipeline = playbin;
+   ev->thread = ecore_thread_run(_emotion_gstreamer_pause,
+                                 _emotion_gstreamer_end,
+                                 _emotion_gstreamer_cancel,
+                                 ev);
 
    /** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */
    /** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */