forked from enlightenment/efl
emotion: make gstreamer backend async and handle it correctly every where.
SVN revision: 62010
This commit is contained in:
parent
1cffa73758
commit
828b67374e
|
@ -82,6 +82,7 @@ struct _Smart_Data
|
||||||
|
|
||||||
double ratio;
|
double ratio;
|
||||||
double pos;
|
double pos;
|
||||||
|
double remember_jump;
|
||||||
double seek_pos;
|
double seek_pos;
|
||||||
double len;
|
double len;
|
||||||
|
|
||||||
|
@ -89,7 +90,9 @@ struct _Smart_Data
|
||||||
|
|
||||||
Emotion_Suspend state;
|
Emotion_Suspend state;
|
||||||
|
|
||||||
|
Eina_Bool open : 1;
|
||||||
Eina_Bool play : 1;
|
Eina_Bool play : 1;
|
||||||
|
Eina_Bool remember_play : 1;
|
||||||
Eina_Bool seek : 1;
|
Eina_Bool seek : 1;
|
||||||
Eina_Bool seeking : 1;
|
Eina_Bool seeking : 1;
|
||||||
};
|
};
|
||||||
|
@ -329,8 +332,10 @@ emotion_object_init(Evas_Object *obj, const char *module_filename)
|
||||||
sd->spu.button = -1;
|
sd->spu.button = -1;
|
||||||
sd->ratio = 1.0;
|
sd->ratio = 1.0;
|
||||||
sd->pos = 0;
|
sd->pos = 0;
|
||||||
|
sd->remember_jump = 0;
|
||||||
sd->seek_pos = 0;
|
sd->seek_pos = 0;
|
||||||
sd->len = 0;
|
sd->len = 0;
|
||||||
|
sd->remember_play = 0;
|
||||||
|
|
||||||
_emotion_module_close(sd->module, sd->video);
|
_emotion_module_close(sd->module, sd->video);
|
||||||
sd->module = NULL;
|
sd->module = NULL;
|
||||||
|
@ -370,6 +375,7 @@ emotion_object_file_set(Evas_Object *obj, const char *file)
|
||||||
sd->module->file_close(sd->video);
|
sd->module->file_close(sd->video);
|
||||||
evas_object_image_data_set(sd->obj, NULL);
|
evas_object_image_data_set(sd->obj, NULL);
|
||||||
evas_object_image_size_set(sd->obj, 1, 1);
|
evas_object_image_size_set(sd->obj, 1, 1);
|
||||||
|
sd->open = 0;
|
||||||
if (!sd->module->file_open(sd->file, obj, sd->video))
|
if (!sd->module->file_open(sd->file, obj, sd->video))
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
sd->module->size_get(sd->video, &w, &h);
|
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 (play == sd->play) return;
|
||||||
if (!sd->module) return;
|
if (!sd->module) return;
|
||||||
if (!sd->video) return;
|
if (!sd->video) return;
|
||||||
|
if (!sd->open)
|
||||||
|
{
|
||||||
|
sd->remember_play = play;
|
||||||
|
return;
|
||||||
|
}
|
||||||
sd->play = play;
|
sd->play = play;
|
||||||
|
sd->remember_play = play;
|
||||||
if (sd->state != EMOTION_WAKEUP) emotion_object_suspend_set(obj, EMOTION_WAKEUP);
|
if (sd->state != EMOTION_WAKEUP) emotion_object_suspend_set(obj, EMOTION_WAKEUP);
|
||||||
if (sd->play) sd->module->play(sd->video, sd->pos);
|
if (sd->play) sd->module->play(sd->video, sd->pos);
|
||||||
else sd->module->stop(sd->video);
|
else sd->module->stop(sd->video);
|
||||||
|
@ -445,6 +457,12 @@ emotion_object_position_set(Evas_Object *obj, double sec)
|
||||||
DBG("sec=%f", sec);
|
DBG("sec=%f", sec);
|
||||||
if (!sd->module) return;
|
if (!sd->module) return;
|
||||||
if (!sd->video) return;
|
if (!sd->video) return;
|
||||||
|
if (!sd->open)
|
||||||
|
{
|
||||||
|
sd->remember_jump = sec;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
sd->remember_jump = 0;
|
||||||
sd->seek_pos = sec;
|
sd->seek_pos = sec;
|
||||||
sd->seek = 1;
|
sd->seek = 1;
|
||||||
sd->pos = sd->seek_pos;
|
sd->pos = sd->seek_pos;
|
||||||
|
@ -1064,7 +1082,11 @@ emotion_object_last_position_load(Evas_Object *obj)
|
||||||
|
|
||||||
EINA_REFCOUNT_REF(sd);
|
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
|
#else
|
||||||
# ifdef HAVE_XATTR
|
# ifdef HAVE_XATTR
|
||||||
{
|
{
|
||||||
|
@ -1266,6 +1288,15 @@ _emotion_decode_stop(Evas_Object *obj)
|
||||||
EAPI void
|
EAPI void
|
||||||
_emotion_open_done(Evas_Object *obj)
|
_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);
|
evas_object_smart_callback_call(obj, SIG_OPEN_DONE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -355,6 +355,12 @@ em_shutdown(void *video)
|
||||||
if (!ev)
|
if (!ev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (ev->thread)
|
||||||
|
{
|
||||||
|
ecore_thread_cancel(ev->thread);
|
||||||
|
ev->thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ev->pipeline)
|
if (ev->pipeline)
|
||||||
{
|
{
|
||||||
gst_element_set_state(ev->pipeline, GST_STATE_NULL);
|
gst_element_set_state(ev->pipeline, GST_STATE_NULL);
|
||||||
|
@ -381,8 +387,6 @@ em_file_open(const char *file,
|
||||||
Emotion_Gstreamer_Video *ev;
|
Emotion_Gstreamer_Video *ev;
|
||||||
Eina_Strbuf *sbuf = NULL;
|
Eina_Strbuf *sbuf = NULL;
|
||||||
const char *uri;
|
const char *uri;
|
||||||
double start, end;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
ev = (Emotion_Gstreamer_Video *)video;
|
||||||
|
|
||||||
|
@ -410,28 +414,20 @@ em_file_open(const char *file,
|
||||||
eina_strbuf_append(sbuf, file);
|
eina_strbuf_append(sbuf, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
start = ecore_time_get();
|
|
||||||
uri = sbuf ? eina_strbuf_string_get(sbuf) : file;
|
uri = sbuf ? eina_strbuf_string_get(sbuf) : file;
|
||||||
DBG("setting file to '%s'", uri);
|
DBG("setting file to '%s'", uri);
|
||||||
ev->pipeline = gstreamer_video_sink_new(ev, obj, uri);
|
ev->pipeline = gstreamer_video_sink_new(ev, obj, uri);
|
||||||
if (sbuf) eina_strbuf_free(sbuf);
|
if (sbuf) eina_strbuf_free(sbuf);
|
||||||
end = ecore_time_get();
|
|
||||||
DBG("Pipeline creation: %f", end - start);
|
|
||||||
|
|
||||||
if (!ev->pipeline)
|
if (!ev->pipeline)
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
|
|
||||||
eina_threads_init();
|
|
||||||
|
|
||||||
start = ecore_time_get();
|
|
||||||
ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline));
|
ev->eos_bus = gst_pipeline_get_bus(GST_PIPELINE(ev->pipeline));
|
||||||
if (!ev->eos_bus)
|
if (!ev->eos_bus)
|
||||||
{
|
{
|
||||||
ERR("could not get the bus");
|
ERR("could not get the bus");
|
||||||
return EINA_FALSE;
|
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);
|
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;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,6 +456,12 @@ em_file_close(void *video)
|
||||||
ev->eos_bus = NULL;
|
ev->eos_bus = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ev->thread)
|
||||||
|
{
|
||||||
|
ecore_thread_cancel(ev->thread);
|
||||||
|
ev->thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ev->pipeline)
|
if (ev->pipeline)
|
||||||
{
|
{
|
||||||
gst_element_set_state(ev->pipeline, GST_STATE_NULL);
|
gst_element_set_state(ev->pipeline, GST_STATE_NULL);
|
||||||
|
@ -719,13 +469,12 @@ em_file_close(void *video)
|
||||||
ev->pipeline = NULL;
|
ev->pipeline = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
eina_threads_shutdown();
|
|
||||||
|
|
||||||
/* we clear the stream lists */
|
/* we clear the stream lists */
|
||||||
EINA_LIST_FREE(ev->audio_streams, astream)
|
EINA_LIST_FREE(ev->audio_streams, astream)
|
||||||
free(astream);
|
free(astream);
|
||||||
EINA_LIST_FREE(ev->video_streams, vstream)
|
EINA_LIST_FREE(ev->video_streams, vstream)
|
||||||
free(vstream);
|
free(vstream);
|
||||||
|
ev->pipeline_parsed = EINA_FALSE;
|
||||||
|
|
||||||
/* shutdown eos */
|
/* shutdown eos */
|
||||||
if (ev->metadata)
|
if (ev->metadata)
|
||||||
|
@ -772,17 +521,21 @@ em_size_get(void *video,
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)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 (vstream)
|
||||||
{
|
{
|
||||||
if (width) *width = vstream->width;
|
if (width) *width = vstream->width;
|
||||||
if (height) *height = vstream->height;
|
if (height) *height = vstream->height;
|
||||||
|
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
on_error:
|
||||||
if (width) *width = 0;
|
if (width) *width = 0;
|
||||||
if (height) *height = 0;
|
if (height) *height = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -833,7 +586,7 @@ em_len_get(void *video)
|
||||||
if (fmt != GST_FORMAT_TIME)
|
if (fmt != GST_FORMAT_TIME)
|
||||||
{
|
{
|
||||||
DBG("requrested duration in time, but got %s instead.",
|
DBG("requrested duration in time, but got %s instead.",
|
||||||
gst_format_get_name(fmt));
|
gst_format_get_name(fmt));
|
||||||
goto fallback;
|
goto fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,6 +596,9 @@ em_len_get(void *video)
|
||||||
return val / 1000000000.0;
|
return val / 1000000000.0;
|
||||||
|
|
||||||
fallback:
|
fallback:
|
||||||
|
if (!_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE))
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
EINA_LIST_FOREACH(ev->audio_streams, l, astream)
|
EINA_LIST_FOREACH(ev->audio_streams, l, astream)
|
||||||
if (astream->length_time >= 0)
|
if (astream->length_time >= 0)
|
||||||
return astream->length_time;
|
return astream->length_time;
|
||||||
|
@ -862,7 +618,10 @@ em_fps_num_get(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)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)
|
if (vstream)
|
||||||
return vstream->fps_num;
|
return vstream->fps_num;
|
||||||
|
|
||||||
|
@ -877,7 +636,10 @@ em_fps_den_get(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)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)
|
if (vstream)
|
||||||
return vstream->fps_den;
|
return vstream->fps_den;
|
||||||
|
|
||||||
|
@ -892,7 +654,10 @@ em_fps_get(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)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)
|
if (vstream)
|
||||||
return (double)vstream->fps_num / (double)vstream->fps_den;
|
return (double)vstream->fps_num / (double)vstream->fps_den;
|
||||||
|
|
||||||
|
@ -986,6 +751,8 @@ em_video_handled(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
ev = (Emotion_Gstreamer_Video *)video;
|
||||||
|
|
||||||
|
_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
|
||||||
|
|
||||||
if (!eina_list_count(ev->video_streams))
|
if (!eina_list_count(ev->video_streams))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -999,6 +766,8 @@ em_audio_handled(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
ev = (Emotion_Gstreamer_Video *)video;
|
||||||
|
|
||||||
|
_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
|
||||||
|
|
||||||
if (!eina_list_count(ev->audio_streams))
|
if (!eina_list_count(ev->audio_streams))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1020,11 +789,14 @@ static Emotion_Format
|
||||||
em_format_get(void *video)
|
em_format_get(void *video)
|
||||||
{
|
{
|
||||||
Emotion_Gstreamer_Video *ev;
|
Emotion_Gstreamer_Video *ev;
|
||||||
Emotion_Video_Stream *vstream;
|
Emotion_Video_Stream *vstream;
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)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 EMOTION_FORMAT_NONE;
|
||||||
|
|
||||||
|
vstream = eina_list_nth(ev->video_streams, ev->video_stream_nbr - 1);
|
||||||
if (vstream)
|
if (vstream)
|
||||||
{
|
{
|
||||||
switch (vstream->fourcc)
|
switch (vstream->fourcc)
|
||||||
|
@ -1048,21 +820,25 @@ static void
|
||||||
em_video_data_size_get(void *video, int *w, int *h)
|
em_video_data_size_get(void *video, int *w, int *h)
|
||||||
{
|
{
|
||||||
Emotion_Gstreamer_Video *ev;
|
Emotion_Gstreamer_Video *ev;
|
||||||
Emotion_Video_Stream *vstream;
|
Emotion_Video_Stream *vstream;
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)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 (vstream)
|
||||||
{
|
{
|
||||||
*w = vstream->width;
|
*w = vstream->width;
|
||||||
*h = vstream->height;
|
*h = vstream->height;
|
||||||
|
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
on_error:
|
||||||
*w = 0;
|
*w = 0;
|
||||||
*h = 0;
|
*h = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1105,6 +881,8 @@ em_video_channel_count(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
ev = (Emotion_Gstreamer_Video *)video;
|
||||||
|
|
||||||
|
_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
|
||||||
|
|
||||||
return eina_list_count(ev->video_streams);
|
return eina_list_count(ev->video_streams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1129,6 +907,8 @@ em_video_channel_get(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
ev = (Emotion_Gstreamer_Video *)video;
|
||||||
|
|
||||||
|
_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
|
||||||
|
|
||||||
return ev->video_stream_nbr;
|
return ev->video_stream_nbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1169,6 +949,8 @@ em_audio_channel_count(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
ev = (Emotion_Gstreamer_Video *)video;
|
||||||
|
|
||||||
|
_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
|
||||||
|
|
||||||
return eina_list_count(ev->audio_streams);
|
return eina_list_count(ev->audio_streams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1193,6 +975,8 @@ em_audio_channel_get(void *video)
|
||||||
|
|
||||||
ev = (Emotion_Gstreamer_Video *)video;
|
ev = (Emotion_Gstreamer_Video *)video;
|
||||||
|
|
||||||
|
_emotion_gstreamer_video_pipeline_parse(ev, EINA_FALSE);
|
||||||
|
|
||||||
return ev->audio_stream_nbr;
|
return ev->audio_stream_nbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1688,3 +1472,276 @@ _eos_sync_fct(GstBus *bus, GstMessage *msg, gpointer data)
|
||||||
|
|
||||||
return GST_BUS_DROP;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ struct _Emotion_Gstreamer_Video
|
||||||
{
|
{
|
||||||
/* Gstreamer elements */
|
/* Gstreamer elements */
|
||||||
GstElement *pipeline;
|
GstElement *pipeline;
|
||||||
|
Ecore_Thread *thread;
|
||||||
|
|
||||||
/* eos */
|
/* eos */
|
||||||
GstBus *eos_bus;
|
GstBus *eos_bus;
|
||||||
|
@ -85,10 +86,11 @@ struct _Emotion_Gstreamer_Video
|
||||||
|
|
||||||
Emotion_Vis vis;
|
Emotion_Vis vis;
|
||||||
|
|
||||||
unsigned char play : 1;
|
Eina_Bool play : 1;
|
||||||
unsigned char play_started : 1;
|
Eina_Bool play_started : 1;
|
||||||
unsigned char video_mute : 1;
|
Eina_Bool video_mute : 1;
|
||||||
unsigned char audio_mute : 1;
|
Eina_Bool audio_mute : 1;
|
||||||
|
Eina_Bool pipeline_parsed : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _EvasVideoSink {
|
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,
|
Emotion_Gstreamer_Message *emotion_gstreamer_message_alloc(Emotion_Gstreamer_Video *ev,
|
||||||
GstMessage *msg);
|
GstMessage *msg);
|
||||||
void emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send);
|
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__ */
|
#endif /* __EMOTION_GSTREAMER_H__ */
|
||||||
|
|
|
@ -341,6 +341,11 @@ static void evas_video_sink_main_render(void *data)
|
||||||
gst_data = GST_BUFFER_DATA(buffer);
|
gst_data = GST_BUFFER_DATA(buffer);
|
||||||
if (!gst_data) goto exit_point;
|
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
|
// This prevent a race condition when data are still in the pipe
|
||||||
// but the buffer size as changed because of a request from
|
// but the buffer size as changed because of a request from
|
||||||
// emotion smart (like on a file set).
|
// 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)
|
if (w != priv->width || h != priv->height)
|
||||||
goto exit_point;
|
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_size_set(priv->o, priv->width, priv->height);
|
||||||
evas_object_image_alpha_set(priv->o, 0);
|
evas_object_image_alpha_set(priv->o, 0);
|
||||||
evas_object_image_colorspace_set(priv->o, priv->eformat);
|
evas_object_image_colorspace_set(priv->o, priv->eformat);
|
||||||
|
@ -619,6 +621,29 @@ gstreamer_plugin_init (GstPlugin * plugin)
|
||||||
EVAS_TYPE_VIDEO_SINK);
|
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 *
|
GstElement *
|
||||||
gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
||||||
Evas_Object *o,
|
Evas_Object *o,
|
||||||
|
@ -628,7 +653,6 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
||||||
GstElement *sink;
|
GstElement *sink;
|
||||||
Evas_Object *obj;
|
Evas_Object *obj;
|
||||||
GstStateChangeReturn res;
|
GstStateChangeReturn res;
|
||||||
double start, end;
|
|
||||||
|
|
||||||
obj = _emotion_image_get(o);
|
obj = _emotion_image_get(o);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
|
@ -637,17 +661,13 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
start = ecore_time_get();
|
|
||||||
playbin = gst_element_factory_make("playbin2", "playbin");
|
playbin = gst_element_factory_make("playbin2", "playbin");
|
||||||
if (!playbin)
|
if (!playbin)
|
||||||
{
|
{
|
||||||
ERR("Unable to create 'playbin' GstElement.");
|
ERR("Unable to create 'playbin' GstElement.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
end = ecore_time_get();
|
|
||||||
DBG("Playbin2: %f", end - start);
|
|
||||||
|
|
||||||
start = ecore_time_get();
|
|
||||||
sink = gst_element_factory_make("emotion-sink", "sink");
|
sink = gst_element_factory_make("emotion-sink", "sink");
|
||||||
if (!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(playbin), "uri", uri, NULL);
|
||||||
g_object_set(G_OBJECT(sink), "evas-object", obj, NULL);
|
g_object_set(G_OBJECT(sink), "evas-object", obj, NULL);
|
||||||
|
|
||||||
end = ecore_time_get();
|
ev->pipeline = playbin;
|
||||||
|
ev->thread = ecore_thread_run(_emotion_gstreamer_pause,
|
||||||
DBG("emotion-sink: %f", end - start);
|
_emotion_gstreamer_end,
|
||||||
|
_emotion_gstreamer_cancel,
|
||||||
start = ecore_time_get();
|
ev);
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/** NOTE: you need to set: GST_DEBUG_DUMP_DOT_DIR=/tmp EMOTION_ENGINE=gstreamer to save the $EMOTION_GSTREAMER_DOT file in '/tmp' */
|
/** 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 */
|
/** then call dot -Tpng -oemotion_pipeline.png /tmp/$TIMESTAMP-$EMOTION_GSTREAMER_DOT.dot */
|
||||||
|
|
Loading…
Reference in New Issue