}
static void
+__mmplayer_print_tag_foreach(const GstTagList *tags, const gchar *tag, gpointer user_data)
+{
+ GValue val = { 0, };
+ gchar *str = NULL;
+ gint depth = GPOINTER_TO_INT(user_data);
+
+ if (!gst_tag_list_copy_value(&val, tags, tag))
+ return;
+
+ if (G_VALUE_HOLDS_STRING(&val))
+ str = g_value_dup_string(&val);
+ else
+ str = gst_value_serialize(&val);
+
+ LOGD("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick(tag), str);
+ g_free(str);
+ g_value_unset(&val);
+}
+
+static void
+__mmplayer_dump_collection(GstStreamCollection * collection)
+{
+ guint i = 0;
+ GstTagList *tags = NULL;
+ GstCaps *caps = NULL;
+
+ for (i = 0; i < gst_stream_collection_get_size(collection); i++) {
+ GstStream *stream = gst_stream_collection_get_stream(collection, i);
+ LOGD ("collection: Stream %u type %s flags 0x%x\n", i,
+ gst_stream_type_get_name(gst_stream_get_stream_type(stream)),
+ gst_stream_get_stream_flags(stream));
+ LOGD (" ID: %s\n", gst_stream_get_stream_id(stream));
+
+ caps = gst_stream_get_caps(stream);
+ if (caps) {
+ gchar *caps_str = gst_caps_to_string(caps);
+ LOGD (" caps: %s\n", caps_str);
+ g_free(caps_str);
+ gst_caps_unref(caps);
+ }
+
+ tags = gst_stream_get_tags(stream);
+ if (tags) {
+ LOGD (" tags:\n");
+ gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(3));
+ gst_tag_list_unref(tags);
+ }
+ }
+}
+
+static void
+__mmplayer_stream_notify_cb(GstStreamCollection *collection,
+ GstStream *stream, GParamSpec *pspec, gpointer data)
+{
+
+ LOGD ("Got stream-notify from stream %s for %s (collection %p)\n",
+ stream->stream_id, pspec->name, collection);
+ if (g_str_equal(pspec->name, "caps")) {
+ GstCaps *caps = gst_stream_get_caps(stream);
+ gchar *caps_str = gst_caps_to_string(caps);
+ LOGD (" New caps: %s\n", caps_str);
+ g_free(caps_str);
+ gst_caps_unref(caps);
+ }
+}
+
+static void
__mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)(data);
__mmplayer_gst_handle_async_done_message(player, msg);
break;
case GST_MESSAGE_STREAM_COLLECTION:
+ {
+ GstStreamCollection *collection = NULL;
LOGD("GST_MESSAGE_STREAM_COLLECTION : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
- break;
+
+ gst_message_parse_stream_collection(msg, &collection);
+ if (collection) {
+ __mmplayer_dump_collection(collection);
+ if (player->collection && player->stream_notify_id) {
+ g_signal_handler_disconnect(player->collection, player->stream_notify_id);
+ player->stream_notify_id = 0;
+ }
+ gst_object_replace((GstObject **)&player->collection, (GstObject *)collection);
+ if (player->collection) {
+ player->stream_notify_id = g_signal_connect(player->collection, "stream-notify",
+ (GCallback)__mmplayer_stream_notify_cb, player);
+ }
+ gst_object_unref(collection);
+ }
+ } break;
case GST_MESSAGE_STREAMS_SELECTED:
+ {
+ GstStreamCollection *collection = NULL;
LOGD("GST_MESSAGE_STREAMS_SELECTED : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
- break;
+
+ gst_message_parse_streams_selected(msg, &collection);
+ if (collection) {
+ guint i = 0, len = 0;
+ len = gst_message_streams_selected_get_size(msg);
+ for (i = 0; i < len; i++) {
+ GstStream *stream = gst_message_streams_selected_get_stream(msg, i);
+ LOGD (" Stream #%d : %s\n", i, gst_stream_get_stream_id(stream));
+ gst_object_unref(stream);
+ }
+ gst_object_unref (collection);
+ }
+ } break;
#ifdef __DEBUG__
case GST_MESSAGE_REQUEST_STATE: LOGD("GST_MESSAGE_REQUEST_STATE"); break;
return;
}
- player->pipeline->mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
- player->pipeline->mainbin[MMPLAYER_M_SRC].gst = source;
-
/* get attribute */
mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
return;
}
+static void
+__mmplayer_source_setup_cb(GstElement *element, GstElement *source, gpointer data)
+{
+ mmplayer_t *player = (mmplayer_t *)data;
+ LOGD("%s >> %s", GST_ELEMENT_NAME(element), GST_ELEMENT_NAME(source));
+
+ player->pipeline->mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
+ player->pipeline->mainbin[MMPLAYER_M_SRC].gst = source;
+
+ if (MMPLAYER_IS_HTTP_STREAMING(player)) {
+ __mmplayer_http_src_setup(element, source, data);
+ } else if (MMPLAYER_IS_SMOOTH_STREAMING(player)) {
+ g_object_set(G_OBJECT(source), "timeout", DEFAULT_HTTP_TIMEOUT, NULL);
+ }
+}
+
gint __mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection,
GstStream * stream, gpointer data)
{
factory_name, GST_ELEMENT_NAME(element));
/* keep the first typefind reference only */
- if (!mainbin[MMPLAYER_M_TYPEFIND].gst && g_strrstr(factory_name, "typefind")) {
+ if (!mainbin[MMPLAYER_M_TYPEFIND].gst && g_strrstr(factory_name, "typefind")) { // FIXME : not required for local playback+
mainbin[MMPLAYER_M_TYPEFIND].id = MMPLAYER_M_TYPEFIND;
mainbin[MMPLAYER_M_TYPEFIND].gst = element;
_mmplayer_add_signal_connection(player, G_OBJECT(element),
MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type", G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
+ LOGD("typefind reference is added");
+ return;
+ }
- } else if (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst && g_strrstr(factory_name, "queue2")) {
+ if (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst && g_strrstr(factory_name, "queue2")) { // fix me :streaming only..
gint64 dur_bytes = 0L;
muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
type,
(guint64)dur_bytes); /* no meaning at the moment */
- } else if (g_strrstr(factory_name, "parsebin")) {
+ return;
+ }
+ if (g_strrstr(factory_name, "parsebin")) {
if (!mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) {
GstIterator *iter = NULL;
GValue item = {0, };
GstElement *ch_element = NULL;
GstElementFactory *ch_factory = NULL;
- g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL);
-
iter = gst_bin_iterate_recurse(child);
if (iter != NULL) {
while (gst_iterator_next(iter, &item) == GST_ITERATOR_OK) {
gst_iterator_free(iter);
}
}
+ }
+
+ if (g_strrstr(factory_name, "parsebin")) {
+
+ g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL);
+ g_object_set(G_OBJECT(element), "message-forward", TRUE, NULL);
+
mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].id = MMPLAYER_M_AUTOPLUG_PARSEBIN;
mainbin[MMPLAYER_M_AUTOPLUG_PARSEBIN].gst = element;
_mmplayer_add_signal_connection(player, G_OBJECT(element),
SECURE_LOGD("uri : %s", player->profile.uri);
/* setting property to streaming source */
- g_object_set(G_OBJECT(uridecodebin3), "uri", player->profile.uri, "message-forward", TRUE, NULL);
+ g_object_set(G_OBJECT(uridecodebin3), "uri", player->profile.uri,
+ "message-forward", TRUE,
+ "buffer-size", DEFAULT_BUFFER_SIZE_BYTES, NULL);
_mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
- MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "source-setup", G_CALLBACK(__mmplayer_http_src_setup), (gpointer)player);
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "source-setup", G_CALLBACK(__mmplayer_source_setup_cb), (gpointer)player);
_mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added", G_CALLBACK(_mmplayer_gst_decode_pad_added), (gpointer)player);
return MM_ERROR_NONE;
}
+static int
+__mmplayer_gst_build_pipeline_with_src(mmplayer_t *player)
+{
+ mmplayer_gst_element_t *mainbin = NULL;
+ GstElement *autoplug_elem = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ mainbin = player->pipeline->mainbin;
+
+ LOGD("uri type %d", player->profile.uri_type);
+
+ autoplug_elem = __mmplayer_gst_make_uridecodebin(player);
+ if (!autoplug_elem) {
+ LOGE("failed to create uridecodebin3 element");
+ goto ERROR;
+ }
+
+ LOGD("autoplug elem is created %s", GST_ELEMENT_NAME(autoplug_elem));
+ mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
+ mainbin[MMPLAYER_M_AUTOPLUG].gst = autoplug_elem;
+
+ if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), autoplug_elem)) {
+ LOGE("failed to add uridecodebin to pipeline");
+ goto ERROR;
+ }
+
+ /* FIXME: required ?*/
+ /* create fakesink element for keeping the pipeline state PAUSED. if needed */
+ mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
+ mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
+
+ if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
+ LOGE("failed to create fakesink");
+ goto ERROR;
+ }
+ GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
+
+ /* take ownership of fakesink. we are reusing it */
+ gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
+
+ if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
+ LOGE("failed to add fakesink to bin");
+ gst_object_unref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
+ goto ERROR;
+ }
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+
+ERROR:
+
+ if (mainbin[MMPLAYER_M_AUTOPLUG].gst)
+ gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_AUTOPLUG].gst));
+
+ if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
+ gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
+
+ mainbin[MMPLAYER_M_AUTOPLUG].gst = NULL;
+ mainbin[MMPLAYER_M_SRC_FAKESINK].gst = NULL;
+
+ return MM_ERROR_PLAYER_INTERNAL;
+}
+
int
_mmplayer_gst_build_pipeline(mmplayer_t *player)
{
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
- mainbin = player->pipeline->mainbin;
-
LOGD("uri type %d", player->profile.uri_type);
/* create source element */
src_elem = __mmplayer_gst_make_rtsp_src(player);
break;
case MM_PLAYER_URI_TYPE_URL_HTTP:
- if (player->ini.use_uridecodebin3) { /* or MMPLAYER_USE_URIDECODEBIN3(player) */
+ if (player->ini.use_uridecodebin3) {
LOGD("uridecodebin include src element.");
- goto ADD_DECODEBIN;
+ return __mmplayer_gst_build_pipeline_with_src(player);
}
src_elem = __mmplayer_gst_make_http_src(player);
break;
case MM_PLAYER_URI_TYPE_FILE:
+ if (player->ini.use_uridecodebin3) {
+ if (!_mmplayer_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
+ LOGE("failed to get storage info");
+ break;
+ }
+ LOGD("uridecodebin include src element.");
+ return __mmplayer_gst_build_pipeline_with_src(player);
+ }
src_elem = __mmplayer_gst_make_file_src(player);
break;
case MM_PLAYER_URI_TYPE_SS:
{
gint http_timeout = DEFAULT_HTTP_TIMEOUT;
+ if (player->ini.use_uridecodebin3) {
+ LOGD("uridecodebin include src element.");
+ return __mmplayer_gst_build_pipeline_with_src(player);
+ }
+
src_elem = gst_element_factory_make("souphttpsrc", "http streaming source");
if (!src_elem) {
LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
return MM_ERROR_PLAYER_INTERNAL;
}
+ mainbin = player->pipeline->mainbin;
+
/* take source element */
LOGD("source elem is created %s", GST_ELEMENT_NAME(src_elem));
mainbin[MMPLAYER_M_SRC].gst = src_elem;
element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
-ADD_DECODEBIN: /* create next element for auto-plugging */
+ /* create next element for auto-plugging */
if (MMPLAYER_IS_HTTP_STREAMING(player)) {
- if (!src_elem) { /* make uridecodebin3 which include src element */
- autoplug_elem_id = MMPLAYER_M_AUTOPLUG;
- autoplug_elem = __mmplayer_gst_make_uridecodebin(player);
- if (!autoplug_elem) {
- LOGE("failed to create uridecodebin3 element");
- goto ERROR;
- }
- } else {
- autoplug_elem_id = MMPLAYER_M_TYPEFIND;
- autoplug_elem = gst_element_factory_make("typefind", "typefinder");
- if (!autoplug_elem) {
- LOGE("failed to create typefind element");
- goto ERROR;
- }
- _mmplayer_add_signal_connection(player, G_OBJECT(autoplug_elem), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
- G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
+ autoplug_elem_id = MMPLAYER_M_TYPEFIND;
+ autoplug_elem = gst_element_factory_make("typefind", "typefinder");
+ if (!autoplug_elem) {
+ LOGE("failed to create typefind element");
+ goto ERROR;
}
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(autoplug_elem), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
+ G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
} else if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
autoplug_elem_id = MMPLAYER_M_AUTOPLUG;
autoplug_elem = _mmplayer_gst_make_decodebin(player);
goto ERROR;
}
- if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
- if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
- LOGE("Failed to change state of decodebin");
+ if (MMPLAYER_IS_HTTP_STREAMING(player)) {
+ if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) { // ????
+ LOGE("Failed to change state of src element");
goto ERROR;
}
} else {
- if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
- LOGE("Failed to change state of src element");
+ if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("Failed to change state of decodebin");
goto ERROR;
}
}