========================================================================================== */
#include <dlog.h>
#include <mm_error.h>
-#include <mm_attrs_private.h>
#include <gst/app/gstappsrc.h>
#include "mm_player_gst.h"
#include "mm_player_priv.h"
#include "mm_player_attrs.h"
#include "mm_player_utils.h"
+#include "mm_player_tracks.h"
/*===========================================================================================
| |
========================================================================================== */
/*---------------------------------------------------------------------------
-| GLOBAL CONSTANT DEFINITIONS: |
+| LOCAL CONSTANT DEFINITIONS: |
---------------------------------------------------------------------------*/
+#define MMPLAYER_TAG_INDENT 3
-/*---------------------------------------------------------------------------
-| IMPORTED VARIABLE DECLARATIONS: |
----------------------------------------------------------------------------*/
+/*===========================================================================================
+| |
+| FUNCTION DEFINITIONS |
+| |
+========================================================================================== */
+#ifdef __DEBUG__
+static void
+print_tag(const GstTagList *list, const gchar *tag, gpointer unused)
+{
+ gint i, count;
-/*---------------------------------------------------------------------------
-| IMPORTED FUNCTION DECLARATIONS: |
----------------------------------------------------------------------------*/
+ count = gst_tag_list_get_tag_size(list, tag);
-/*---------------------------------------------------------------------------
-| LOCAL #defines: |
----------------------------------------------------------------------------*/
+ LOGD("count = %d", count);
-/*---------------------------------------------------------------------------
-| LOCAL CONSTANT DEFINITIONS: |
----------------------------------------------------------------------------*/
+ for (i = 0; i < count; i++) {
+ gchar *str;
-/*---------------------------------------------------------------------------
-| LOCAL DATA TYPE DEFINITIONS: |
----------------------------------------------------------------------------*/
+ if (gst_tag_get_type(tag) == G_TYPE_STRING) {
+ if (!gst_tag_list_get_string_index(list, tag, i, &str))
+ g_assert_not_reached();
+ } else {
+ str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i));
+ }
-/*---------------------------------------------------------------------------
-| GLOBAL VARIABLE DEFINITIONS: |
----------------------------------------------------------------------------*/
+ if (i == 0)
+ g_print(" %15s: %s", gst_tag_get_nick(tag), str);
+ else
+ g_print(" : %s", str);
-/*---------------------------------------------------------------------------
-| LOCAL VARIABLE DEFINITIONS: |
----------------------------------------------------------------------------*/
+ g_free(str);
+ }
+}
+#endif
-/*---------------------------------------------------------------------------
-| LOCAL FUNCTION PROTOTYPES: |
----------------------------------------------------------------------------*/
+static gboolean
+__mmplayer_check_error_posted_from_activated_track(mmplayer_t *player, gchar *src_element_name)
+{
+ /* check whether the error is posted from not-activated track or not */
+ int msg_src_pos = 0;
+ gint active_index = 0;
-/*===========================================================================================
-| |
-| FUNCTION DEFINITIONS |
-| |
-========================================================================================== */
+ MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst, TRUE);
+
+ active_index = player->track[MM_PLAYER_TRACK_TYPE_AUDIO].active_track_index;
+ LOGD("current active pad index -%d", active_index);
+
+ if (src_element_name) {
+ int idx = 0;
+
+ if (player->audio_decoders) {
+ GList *adec = player->audio_decoders;
+ for (; adec ; adec = g_list_next(adec)) {
+ gchar *name = adec->data;
+
+ LOGD("found audio decoder name = %s", name);
+ if (g_strrstr(name, src_element_name)) {
+ msg_src_pos = idx;
+ break;
+ }
+ idx++;
+ }
+ }
+ LOGD("active pad = %d, error src index = %d", active_index, msg_src_pos);
+ }
+
+ if (active_index != msg_src_pos) {
+ LOGD("skip error because error is posted from no activated track");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int
+__mmplayer_gst_transform_error_decode(mmplayer_t *player, const char *klass)
+{
+ /* Demuxer can't parse one track because it's corrupted.
+ * So, the decoder for it is not linked.
+ * But, it has one playable track.
+ */
+ if (g_strrstr(klass, "Demux")) {
+ if (player->can_support_codec == FOUND_PLUGIN_VIDEO) {
+ return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
+ } else if (player->can_support_codec == FOUND_PLUGIN_AUDIO) {
+ return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
+ } else {
+ if (player->pipeline->audiobin) { // PCM
+ return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
+ } else {
+ LOGD("not found any available codec. Player should be destroyed.");
+ return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
+ }
+ }
+ }
+
+ return MM_ERROR_PLAYER_INVALID_STREAM;
+}
+
+static int
+__mmplayer_gst_transform_error_type(mmplayer_t *player, GstElement *src_element)
+{
+ if (src_element == player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst) {
+ LOGE("Not supported subtitle.");
+ return MM_ERROR_PLAYER_NOT_SUPPORTED_SUBTITLE;
+ }
+ return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
+}
+
+static int
+__mmplayer_gst_transform_error_failed(mmplayer_t *player, const char *klass, GError *error)
+{
+ /* Decoder Custom Message */
+ if (!strstr(error->message, "ongoing"))
+ return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
+
+ if (strncasecmp(klass, "audio", 5)) {
+ if ((player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
+ LOGD("Video can keep playing.");
+ return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
+ }
+ } else if (strncasecmp(klass, "video", 5)) {
+ if ((player->can_support_codec & FOUND_PLUGIN_AUDIO)) {
+ LOGD("Audio can keep playing.");
+ return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
+ }
+ }
+
+ LOGD("not found any available codec. Player should be destroyed.");
+ return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
+}
+
+static int
+__mmplayer_gst_transform_error_decrypt(mmplayer_t *player, GError *error)
+{
+ if (strstr(error->message, "rights expired"))
+ return MM_ERROR_PLAYER_DRM_EXPIRED;
+ else if (strstr(error->message, "no rights"))
+ return MM_ERROR_PLAYER_DRM_NO_LICENSE;
+ else if (strstr(error->message, "has future rights"))
+ return MM_ERROR_PLAYER_DRM_FUTURE_USE;
+ else if (strstr(error->message, "opl violation"))
+ return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
+
+ return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
+}
/* NOTE : decide gstreamer state whether there is some playable track or not. */
static gint
-__mmplayer_gst_transform_gsterror(mm_player_t* player, GstMessage * message, GError* error)
+__mmplayer_gst_transform_gsterror(mmplayer_t *player, GstMessage *message, GError *error)
{
gchar *src_element_name = NULL;
GstElement *src_element = NULL;
GstElementFactory *factory = NULL;
- const gchar* klass = NULL;
+ const gchar *klass = NULL;
MMPLAYER_FENTER();
player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
src_element = GST_ELEMENT_CAST(message->src);
- if (!src_element)
- goto INTERNAL_ERROR;
-
src_element_name = GST_ELEMENT_NAME(src_element);
if (!src_element_name)
- goto INTERNAL_ERROR;
+ return MM_ERROR_PLAYER_INTERNAL;
factory = gst_element_get_factory(src_element);
if (!factory)
- goto INTERNAL_ERROR;
+ return MM_ERROR_PLAYER_INTERNAL;
klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
if (!klass)
- goto INTERNAL_ERROR;
+ return MM_ERROR_PLAYER_INTERNAL;
- LOGD("error code=%d, msg=%s, src element=%s, class=%s\n",
+ LOGD("error code=%d, msg=%s, src element=%s, class=%s",
error->code, error->message, src_element_name, klass);
- /* check whether the error is posted from not-activated track or not */
- if (player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst) {
- int msg_src_pos = 0;
- gint active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
- LOGD("current active pad index -%d", active_pad_index);
-
- if (src_element_name) {
- int idx = 0;
-
- if (player->audio_decoders) {
- GList *adec = player->audio_decoders;
- for (; adec ; adec = g_list_next(adec)) {
- gchar *name = adec->data;
-
- LOGD("found audio decoder name = %s", name);
- if (g_strrstr(name, src_element_name)) {
- msg_src_pos = idx;
- break;
- }
- idx++;
- }
- }
- LOGD("active pad = %d, error src index = %d", active_pad_index, msg_src_pos);
- }
-
- if (active_pad_index != msg_src_pos) {
- LOGD("skip error because error is posted from no activated track");
- return MM_ERROR_NONE;
- }
- }
+ if (MMPLAYER_USE_DECODEBIN(player) &&
+ !__mmplayer_check_error_posted_from_activated_track(player, src_element_name))
+ return MM_ERROR_NONE;
switch (error->code) {
case GST_STREAM_ERROR_DECODE:
- {
- /* Demuxer can't parse one track because it's corrupted.
- * So, the decoder for it is not linked.
- * But, it has one playable track.
- */
- if (g_strrstr(klass, "Demux")) {
- if (player->can_support_codec == FOUND_PLUGIN_VIDEO) {
- return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
- } else if (player->can_support_codec == FOUND_PLUGIN_AUDIO) {
- return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
- } else {
- if (player->pipeline->audiobin) // PCM
- return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
- else
- goto CODEC_NOT_FOUND;
- }
- }
- return MM_ERROR_PLAYER_INVALID_STREAM;
- }
- break;
-
+ return __mmplayer_gst_transform_error_decode(player, klass);
case GST_STREAM_ERROR_CODEC_NOT_FOUND:
case GST_STREAM_ERROR_TYPE_NOT_FOUND:
case GST_STREAM_ERROR_WRONG_TYPE:
- {
- if (src_element == player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst) {
- LOGE("Not supported subtitle.");
- return MM_ERROR_PLAYER_NOT_SUPPORTED_SUBTITLE;
- }
- return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
- }
-
+ return __mmplayer_gst_transform_error_type(player, src_element);
case GST_STREAM_ERROR_FAILED:
- {
- /* Decoder Custom Message */
- if (strstr(error->message, "ongoing")) {
- if (strncasecmp(klass, "audio", 5)) {
- if ((player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
- LOGD("Video can keep playing.\n");
- return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
- } else
- goto CODEC_NOT_FOUND;
-
- } else if (strncasecmp(klass, "video", 5)) {
- if ((player->can_support_codec & FOUND_PLUGIN_AUDIO)) {
- LOGD("Audio can keep playing.\n");
- return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
- } else
- goto CODEC_NOT_FOUND;
- }
- }
- return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
- }
- break;
-
+ return __mmplayer_gst_transform_error_failed(player, klass, error);
case GST_STREAM_ERROR_DECRYPT:
case GST_STREAM_ERROR_DECRYPT_NOKEY:
- {
- LOGE("decryption error, [%s] failed, reason : [%s]\n", src_element_name, error->message);
-
- if (strstr(error->message, "rights expired"))
- return MM_ERROR_PLAYER_DRM_EXPIRED;
- else if (strstr(error->message, "no rights"))
- return MM_ERROR_PLAYER_DRM_NO_LICENSE;
- else if (strstr(error->message, "has future rights"))
- return MM_ERROR_PLAYER_DRM_FUTURE_USE;
- else if (strstr(error->message, "opl violation"))
- return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
- return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
- }
- break;
-
+ LOGE("decryption error, [%s] failed, reason : [%s]", src_element_name, error->message);
+ return __mmplayer_gst_transform_error_decrypt(player, error);
default:
break;
}
MMPLAYER_FLEAVE();
return MM_ERROR_PLAYER_INVALID_STREAM;
-
-INTERNAL_ERROR:
- return MM_ERROR_PLAYER_INTERNAL;
-
-CODEC_NOT_FOUND:
- LOGD("not found any available codec. Player should be destroyed.\n");
- return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
}
gint
-__mmplayer_gst_handle_core_error(mm_player_t* player, int code)
+__mmplayer_gst_handle_core_error(mmplayer_t *player, int code)
{
gint trans_err = MM_ERROR_NONE;
}
gint
-__mmplayer_gst_handle_library_error(mm_player_t* player, int code)
+__mmplayer_gst_handle_library_error(mmplayer_t *player, int code)
{
gint trans_err = MM_ERROR_NONE;
}
gint
-__mmplayer_gst_handle_resource_error(mm_player_t* player, int code, GstMessage * message)
+__mmplayer_gst_handle_resource_error(mmplayer_t *player, int code, GstMessage *message)
{
gint trans_err = MM_ERROR_NONE;
break;
} else if (message != NULL && message->src != NULL) {
storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
- MMPlayerPathType path_type = MMPLAYER_PATH_MAX;
+ mmplayer_path_type_e path_type = MMPLAYER_PATH_MAX;
if (message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst)
path_type = MMPLAYER_PATH_VOD;
}
gint
-__mmplayer_gst_handle_stream_error(mm_player_t* player, GError* error, GstMessage * message)
+__mmplayer_gst_handle_stream_error(mmplayer_t *player, GError *error, GstMessage *message)
{
gint trans_err = MM_ERROR_NONE;
}
gboolean
-__mmplayer_handle_gst_error(mm_player_t* player, GstMessage * message, GError* error)
+__mmplayer_handle_gst_error(mmplayer_t *player, GstMessage *message, GError *error)
{
MMMessageParamType msg_param;
gchar *msg_src_element;
} else if (error->domain == GST_STREAM_ERROR) {
msg_param.code = __mmplayer_gst_handle_stream_error(player, error, message);
} else {
- LOGW("This error domain is not defined.\n");
+ LOGW("This error domain is not defined.");
/* we treat system error as an internal error */
msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
if (message->src) {
msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
- msg_param.data = (void *) error->message;
+ msg_param.data = (void *)error->message;
- LOGE("-Msg src : [%s] Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]\n",
+ LOGE("-Msg src : [%s] Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]",
msg_src_element, g_quark_to_string(error->domain), error->message, error->code, msg_param.code);
}
MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
/* don't post more if one was sent already */
player->msg_posted = TRUE;
- } else
- LOGD("skip error post because it's sent already.\n");
+ } else {
+ LOGD("skip error post because it's sent already.");
+ }
MMPLAYER_FLEAVE();
}
static gboolean
-__mmplayer_handle_streaming_error(mm_player_t* player, GstMessage * message)
+__mmplayer_handle_streaming_error(mmplayer_t *player, GstMessage *message)
{
LOGD("\n");
MMMessageParamType msg_param;
error_string = g_strdup(gst_structure_get_string(s, "error_string"));
if (error_string)
- msg_param.data = (void *) error_string;
+ msg_param.data = (void *)error_string;
if (message->src) {
msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
- LOGE("-Msg src : [%s] Code : [%x] Error : [%s] \n",
- msg_src_element, msg_param.code, (char*)msg_param.data);
+ LOGE("-Msg src : [%s] Code : [0x%x] Error : [%s]",
+ msg_src_element, msg_param.code, (char *)msg_param.data);
}
/* post error to application */
/* don't post more if one was sent already */
player->msg_posted = TRUE;
- } else
- LOGD("skip error post because it's sent already.\n");
+ } else {
+ LOGD("skip error post because it's sent already.");
+ }
gst_structure_free(s);
- g_free(error_string);
+ MMPLAYER_FREEIF(error_string);
MMPLAYER_FLEAVE();
return TRUE;
}
static void
-__mmplayer_get_metadata_360_from_tags(GstTagList *tags, mm_player_spherical_metadata_t *metadata)
+__mmplayer_get_metadata_360_from_tags(GstTagList *tags, mmplayer_spherical_metadata_t *metadata)
{
gst_tag_list_get_int(tags, "is_spherical", &metadata->is_spherical);
gst_tag_list_get_int(tags, "is_stitched", &metadata->is_stitched);
}
static gboolean
-__mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg)
+__mmplayer_gst_extract_tag_from_msg(mmplayer_t *player, GstMessage *msg)
{
/* macro for better code readability */
-#define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
-if (gst_tag_list_get_string(tag_list, gsttag, &string)) {\
- if (string != NULL) { \
- SECURE_LOGD("update tag string : %s\n", string); \
- if (strlen(string) > MM_MAX_STRING_LENGTH) { \
- char *new_string = malloc(MM_MAX_STRING_LENGTH); \
- strncpy(new_string, string, MM_MAX_STRING_LENGTH-1); \
- new_string[MM_MAX_STRING_LENGTH-1] = '\0'; \
- mm_attrs_set_string_by_name(attribute, playertag, new_string); \
- g_free(new_string); \
- new_string = NULL; \
- } else { \
- mm_attrs_set_string_by_name(attribute, playertag, string); \
+#define MMPLAYER_UPDATE_TAG_STRING(gsttag, player, playertag) \
+ do { \
+ if (gst_tag_list_get_string(tag_list, gsttag, &string)) {\
+ if (string != NULL) { \
+ SECURE_LOGD("update tag string : %s", string); \
+ if (strlen(string) > MM_MAX_STRING_LENGTH) { \
+ char *new_string = g_malloc(MM_MAX_STRING_LENGTH); \
+ strncpy(new_string, string, MM_MAX_STRING_LENGTH - 1); \
+ new_string[MM_MAX_STRING_LENGTH - 1] = '\0'; \
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, new_string, strlen(new_string), NULL); \
+ MMPLAYER_FREEIF(new_string); \
+ } else { \
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, string, strlen(string), NULL); \
+ } \
+ MMPLAYER_FREEIF(string); \
+ } \
} \
- g_free(string); \
- string = NULL; \
- } \
-}
-
-#define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
-do { \
- GstSample *sample = NULL;\
- if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample)) {\
- GstMapInfo info = GST_MAP_INFO_INIT;\
- buffer = gst_sample_get_buffer(sample);\
- if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) {\
- LOGD("failed to get image data from tag");\
+ } while (0)
+
+#define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, player, playertag) \
+ do { \
+ GstSample *sample = NULL;\
+ if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample)) {\
+ GstMapInfo info = GST_MAP_INFO_INIT;\
+ buffer = gst_sample_get_buffer(sample);\
+ if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) {\
+ LOGD("failed to get image data from tag");\
+ gst_sample_unref(sample);\
+ return FALSE;\
+ } \
+ SECURE_LOGD("update album cover data : %p, size : %zu", info.data, info.size);\
+ MMPLAYER_FREEIF(player->album_art);\
+ player->album_art = (gchar *)g_malloc(info.size);\
+ if (player->album_art) {\
+ memcpy(player->album_art, info.data, info.size);\
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, (void *)player->album_art, info.size, NULL); \
+ if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {\
+ msg_param.data = (void *)player->album_art;\
+ msg_param.size = info.size;\
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_IMAGE_BUFFER, &msg_param);\
+ SECURE_LOGD("post message image buffer data : %p, size : %zu", info.data, info.size);\
+ } \
+ } \
+ gst_buffer_unmap(buffer, &info);\
gst_sample_unref(sample);\
- return FALSE;\
+ } \
+ } while (0)
+
+#define MMPLAYER_UPDATE_TAG_UINT(gsttag, player, playertag) \
+ do { \
+ if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint)) { \
+ if (v_uint) { \
+ int i = 0; \
+ mmplayer_track_type_e track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
+ if (strstr(GST_OBJECT_NAME(msg->src), "audio")) \
+ track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
+ else if (strstr(GST_OBJECT_NAME(msg->src), "video")) \
+ track_type = MM_PLAYER_TRACK_TYPE_VIDEO; \
+ else \
+ track_type = MM_PLAYER_TRACK_TYPE_TEXT; \
+ if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) { \
+ if (track_type == MM_PLAYER_TRACK_TYPE_AUDIO) \
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ "content_audio_bitrate", v_uint, NULL); \
+ player->bitrate[track_type] = v_uint; \
+ player->total_bitrate = 0; \
+ for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
+ player->total_bitrate += player->bitrate[i]; \
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, player->total_bitrate, NULL); \
+ SECURE_LOGD("update bitrate %d[bps] of stream #%d.", v_uint, (int)track_type); \
+ } else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) { \
+ player->maximum_bitrate[track_type] = v_uint; \
+ player->total_maximum_bitrate = 0; \
+ for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
+ player->total_maximum_bitrate += player->maximum_bitrate[i]; \
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, player->total_maximum_bitrate, NULL); \
+ SECURE_LOGD("update maximum bitrate %d[bps] of stream #%d", v_uint, (int)track_type);\
+ } else { \
+ mm_player_set_attribute((MMHandleType)player, NULL, playertag, v_uint, NULL); \
+ } \
+ v_uint = 0;\
+ } \
} \
- SECURE_LOGD("update album cover data : %p, size : %d\n", info.data, info.size);\
- MMPLAYER_FREEIF(player->album_art);\
- player->album_art = (gchar *)g_malloc(info.size);\
- if (player->album_art) {\
- memcpy(player->album_art, info.data, info.size);\
- mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size);\
- if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {\
- msg_param.data = (void *)player->album_art;\
- msg_param.size = info.size;\
- MMPLAYER_POST_MSG(player, MM_MESSAGE_IMAGE_BUFFER, &msg_param);\
- SECURE_LOGD("post message image buffer data : %p, size : %d\n", info.data, info.size);\
+ } while (0)
+
+#define MMPLAYER_UPDATE_TAG_DATE(gsttag, player, playertag) \
+ do { \
+ if (gst_tag_list_get_date(tag_list, gsttag, &date)) {\
+ if (date != NULL) {\
+ string = g_strdup_printf("%d", g_date_get_year(date));\
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, string, strlen(string), NULL); \
+ SECURE_LOGD("metainfo year : %s", string);\
+ MMPLAYER_FREEIF(string);\
+ g_date_free(date);\
} \
} \
- gst_buffer_unmap(buffer, &info);\
- gst_sample_unref(sample);\
- } \
-} while (0)
-
-#define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
-do { \
- if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint)) { \
- if (v_uint) { \
- int i = 0; \
- gchar *tag_list_str = NULL; \
- MMPlayerTrackType track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
- if (strstr(GST_OBJECT_NAME(msg->src), "audio")) \
- track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
- else if (strstr(GST_OBJECT_NAME(msg->src), "video")) \
- track_type = MM_PLAYER_TRACK_TYPE_VIDEO; \
- else \
- track_type = MM_PLAYER_TRACK_TYPE_TEXT; \
- if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) { \
- if (track_type == MM_PLAYER_TRACK_TYPE_AUDIO) \
- mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
- player->bitrate[track_type] = v_uint; \
- player->total_bitrate = 0; \
- for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
- player->total_bitrate += player->bitrate[i]; \
- mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate); \
- SECURE_LOGD("update bitrate %d[bps] of stream #%d.\n", v_uint, (int)track_type); \
- } else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) { \
- player->maximum_bitrate[track_type] = v_uint; \
- player->total_maximum_bitrate = 0; \
- for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
- player->total_maximum_bitrate += player->maximum_bitrate[i]; \
- mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate);\
- SECURE_LOGD("update maximum bitrate %d[bps] of stream #%d\n", v_uint, (int)track_type);\
- } else { \
- mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
+ } while (0)
+
+#define MMPLAYER_UPDATE_TAG_DATE_TIME(gsttag, player, playertag) \
+ do { \
+ if (gst_tag_list_get_date_time(tag_list, gsttag, &datetime)) {\
+ if (datetime != NULL) {\
+ string = g_strdup_printf("%d", gst_date_time_get_year(datetime));\
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, string, strlen(string), NULL); \
+ SECURE_LOGD("metainfo year : %s", string);\
+ MMPLAYER_FREEIF(string);\
+ gst_date_time_unref(datetime);\
} \
- v_uint = 0;\
- g_free(tag_list_str); \
} \
- } \
-} while (0)
-
-#define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
-if (gst_tag_list_get_date(tag_list, gsttag, &date)) {\
- if (date != NULL) {\
- string = g_strdup_printf("%d", g_date_get_year(date));\
- mm_attrs_set_string_by_name(attribute, playertag, string);\
- SECURE_LOGD("metainfo year : %s\n", string);\
- MMPLAYER_FREEIF(string);\
- g_date_free(date);\
- } \
-}
-
-#define MMPLAYER_UPDATE_TAG_DATE_TIME(gsttag, attribute, playertag) \
-if (gst_tag_list_get_date_time(tag_list, gsttag, &datetime)) {\
- if (datetime != NULL) {\
- string = g_strdup_printf("%d", gst_date_time_get_year(datetime));\
- mm_attrs_set_string_by_name(attribute, playertag, string);\
- SECURE_LOGD("metainfo year : %s\n", string);\
- MMPLAYER_FREEIF(string);\
- gst_date_time_unref(datetime);\
- } \
-}
-
-#define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
-if (gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64)) {\
- if (v_uint64) {\
- /* FIXIT : don't know how to store date */\
- g_assert(1);\
- v_uint64 = 0;\
- } \
-}
-
-#define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
-if (gst_tag_list_get_double(tag_list, gsttag, &v_double)) {\
- if (v_double) {\
- /* FIXIT : don't know how to store date */\
- g_assert(1);\
- v_double = 0;\
- } \
-}
+ } while (0)
/* function start */
- GstTagList* tag_list = NULL;
-
- MMHandleType attrs = 0;
+ GstTagList *tag_list = NULL;
char *string = NULL;
guint v_uint = 0;
MMPLAYER_RETURN_VAL_IF_FAIL(player && msg, FALSE);
- attrs = MMPLAYER_GET_ATTRS(player);
-
- MMPLAYER_RETURN_VAL_IF_FAIL(attrs, FALSE);
-
/* get tag list from gst message */
gst_message_parse_tag(msg, &tag_list);
/* store tags to player attributes */
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
- MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
- MMPLAYER_UPDATE_TAG_DATE_TIME(GST_TAG_DATE_TIME, attrs, "tag_date");
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
- MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
- /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
- MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
- MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, player, "tag_title");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, player, "tag_artist");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, player, "tag_album");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, player, "tag_author");
+ MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, player, "tag_date");
+ MMPLAYER_UPDATE_TAG_DATE_TIME(GST_TAG_DATE_TIME, player, "tag_date");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, player, "tag_genre");
+ MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, player, "tag_track_num");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, player, "tag_description");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, player, "tag_copyright");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, player, "content_video_codec");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, player, "content_audio_codec");
+ MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, player, "content_bitrate");
+ MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, player, "content_max_bitrate");
MMPLAYER_UPDATE_TAG_LOCK(player);
- MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
+ MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, player, "tag_album_cover");
MMPLAYER_UPDATE_TAG_UNLOCK(player);
- /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
- /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
- MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
+ MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, player, "content_video_orientation");
if (strstr(GST_OBJECT_NAME(msg->src), "demux")) {
if (player->video360_metadata.is_spherical == -1) {
__mmplayer_get_metadata_360_from_tags(tag_list, &player->video360_metadata);
- mm_attrs_set_int_by_name(attrs, "content_video_is_spherical",
- player->video360_metadata.is_spherical);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_video_is_spherical", player->video360_metadata.is_spherical, NULL);
if (player->video360_metadata.is_spherical == 1) {
LOGD("This is spherical content for 360 playback.");
player->is_content_spherical = TRUE;
if (!strcmp(player->video360_metadata.projection_type_string, "equirectangular")) {
player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
} else {
- LOGE("Projection %s: code not implemented.\n", player->video360_metadata.projection_type_string);
+ LOGE("Projection %s: code not implemented.", player->video360_metadata.projection_type_string);
player->is_content_spherical = player->is_video360_enabled = FALSE;
}
}
} else if (!strcmp(player->video360_metadata.stereo_mode_string, "top-bottom")) {
player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_TOP_BOTTOM;
} else {
- LOGE("Stereo mode %s: code not implemented.\n", player->video360_metadata.stereo_mode_string);
+ LOGE("Stereo mode %s: code not implemented.", player->video360_metadata.stereo_mode_string);
player->is_content_spherical = player->is_video360_enabled = FALSE;
}
}
}
}
- if (mmf_attrs_commit(attrs))
- LOGE("failed to commit.\n");
-
- gst_tag_list_free(tag_list);
+ gst_tag_list_unref(tag_list);
return TRUE;
}
/* if retval is FALSE, it will be dropped for perfomance. */
static gboolean
-__mmplayer_gst_check_useful_message(mm_player_t *player, GstMessage * message)
+__mmplayer_gst_check_useful_message(mmplayer_t *player, GstMessage *message)
{
gboolean retval = FALSE;
case GST_MESSAGE_ELEMENT:
case GST_MESSAGE_DURATION_CHANGED:
case GST_MESSAGE_ASYNC_START:
+ case GST_MESSAGE_STREAM_COLLECTION:
retval = TRUE;
break;
case GST_MESSAGE_ASYNC_DONE:
retval = TRUE;
gst_message_parse_buffering(message, &buffer_percent);
if (buffer_percent != MAX_BUFFER_PERCENT) {
- LOGD("[%s] buffering msg %d%%!!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), buffer_percent);
+ LOGD("[%s] buffering msg %d%%!!", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), buffer_percent);
break;
}
}
if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
- LOGD("[%s] Buffering DONE is detected !!\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
+ LOGD("[%s] Buffering DONE is detected !", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
player->streamer->buffering_state |= MM_PLAYER_BUFFERING_COMPLETE;
}
break;
}
+ case GST_MESSAGE_STREAMS_SELECTED:
+ {
+ if (MMPLAYER_USE_DECODEBIN(player))
+ break; /* drop msg */
+
+ if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
+ (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
+ (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
+
+ gint64 dur_bytes = 0L;
+
+ if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
+ LOGE("fail to get duration.");
+
+ /* there is no mq, enable use-buffering on queue2 (ex) wav streaming
+ * use file information was already set on Q2 when it was created. */
+ _mm_player_streaming_set_queue2(player->streamer,
+ player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
+ TRUE, /* use_buffering */
+ MUXED_BUFFER_TYPE_MAX, /* use previous buffer type setting */
+ ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
+ }
+
+ LOGD("GST_MESSAGE_STREAMS_SELECTED");
+ player->no_more_pad = TRUE;
+ _mmplayer_pipeline_complete(NULL, player);
+ retval = TRUE;
+ break;
+ }
default:
retval = FALSE;
break;
}
static void
-__mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
+__mmplayer_update_buffer_setting(mmplayer_t *player, GstMessage *buffering_msg)
{
- MMHandleType attrs = 0;
guint64 data_size = 0;
- gchar* path = NULL;
gint64 pos_nsec = 0;
- struct stat sb;
MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
- __mmplayer_gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_nsec); /* to update player->last_position */
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("fail to get attributes.\n");
- return;
- }
-
- if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
- mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
+ _mmplayer_gst_get_position(player, &pos_nsec); /* to update player->last_position */
- if (stat(path, &sb) == 0)
- data_size = (guint64)sb.st_size;
- } else if (MMPLAYER_IS_HTTP_STREAMING(player))
+ if (MMPLAYER_IS_HTTP_STREAMING(player)) {
data_size = player->http_content_size;
+ }
- __mm_player_streaming_buffering(player->streamer, buffering_msg, data_size, player->last_position, player->duration);
- __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
+ _mm_player_streaming_buffering(player->streamer, buffering_msg, data_size, player->last_position, player->duration);
+ _mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
return;
}
static int
-__mmplayer_handle_buffering_playback(mm_player_t* player)
+__mmplayer_handle_buffering_playback(mmplayer_t *player)
{
int ret = MM_ERROR_NONE;
- MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
- MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
- MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
- MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
+ mmplayer_state_e prev_state = MM_PLAYER_STATE_NONE;
+ mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
+ mmplayer_state_e target_state = MM_PLAYER_STATE_NONE;
+ mmplayer_state_e pending_state = MM_PLAYER_STATE_NONE;
if (!player || !player->streamer || (MMPLAYER_IS_LIVE_STREAMING(player) && MMPLAYER_IS_RTSP_STREAMING(player))) {
- LOGW("do nothing for buffering msg\n");
+ LOGW("do nothing for buffering msg");
ret = MM_ERROR_PLAYER_INVALID_STATE;
goto exit;
}
{
switch (pending_state) {
case MM_PLAYER_STATE_PLAYING:
- __mmplayer_gst_pause(player, TRUE);
+ _mmplayer_gst_pause(player, TRUE);
break;
case MM_PLAYER_STATE_PAUSED:
- LOGD("player is already going to paused state, there is nothing to do.\n");
+ LOGD("player is already going to paused state, there is nothing to do.");
break;
case MM_PLAYER_STATE_NONE:
case MM_PLAYER_STATE_NULL:
case MM_PLAYER_STATE_READY:
default:
- LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
+ LOGW("invalid pending state [%s].", MMPLAYER_STATE_GET_NAME(pending_state));
break;
}
}
case MM_PLAYER_STATE_NONE:
{
if (current_state != MM_PLAYER_STATE_PLAYING)
- __mmplayer_gst_resume(player, TRUE);
+ _mmplayer_gst_resume(player, TRUE);
}
break;
* Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
*/
if (current_state == MM_PLAYER_STATE_PLAYING) {
- /* NOTE: If the current state is PLAYING, it means, async __mmplayer_gst_pause() is not completed yet.
+ /* NOTE: If the current state is PLAYING, it means, async _mmplayer_gst_pause() is not completed yet.
* The current state should be changed to paused purposely to prevent state conflict.
*/
MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
}
- __mmplayer_gst_resume(player, TRUE);
+ _mmplayer_gst_resume(player, TRUE);
break;
case MM_PLAYER_STATE_PLAYING:
- LOGD("player is already going to playing state, there is nothing to do.\n");
+ LOGD("player is already going to playing state, there is nothing to do.");
break;
case MM_PLAYER_STATE_NULL:
case MM_PLAYER_STATE_READY:
default:
- LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
+ LOGW("invalid pending state [%s].", MMPLAYER_STATE_GET_NAME(pending_state));
break;
}
}
case MM_PLAYER_STATE_READY:
case MM_PLAYER_STATE_NONE:
default:
- LOGW("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state));
+ LOGW("invalid target state [%s].", MMPLAYER_STATE_GET_NAME(target_state));
break;
}
} else {
if (current_state != MM_PLAYER_STATE_PAUSED) {
/* rtsp streaming pause makes rtsp server stop sending data. */
if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
- LOGD("set pause state during buffering\n");
- __mmplayer_gst_pause(player, TRUE);
+ LOGD("set pause state during buffering");
+ _mmplayer_gst_pause(player, TRUE);
}
}
}
case MM_PLAYER_STATE_PLAYING:
/* rtsp streaming pause makes rtsp server stop sending data. */
if (!MMPLAYER_IS_RTSP_STREAMING(player))
- __mmplayer_gst_pause(player, TRUE);
+ _mmplayer_gst_pause(player, TRUE);
break;
case MM_PLAYER_STATE_PAUSED:
case MM_PLAYER_STATE_NULL:
case MM_PLAYER_STATE_READY:
default:
- LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
+ LOGW("invalid pending state [%s].", MMPLAYER_STATE_GET_NAME(pending_state));
break;
}
}
return ret;
}
-static VariantData *
-__mmplayer_adaptive_var_info(const VariantData *self, gpointer user_data)
+static stream_variant_t *
+__mmplayer_adaptive_var_info(const stream_variant_t *self, gpointer user_data)
{
- VariantData *var_info = NULL;
+ stream_variant_t *var_info = NULL;
g_return_val_if_fail(self != NULL, NULL);
- var_info = g_new0(VariantData, 1);
+ var_info = g_new0(stream_variant_t, 1);
if (!var_info) return NULL;
var_info->bandwidth = self->bandwidth;
var_info->width = self->width;
}
static gboolean
-__mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
+__mmplayer_gst_handle_duration(mmplayer_t *player, GstMessage *msg)
{
gint64 bytes = 0;
if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes)) {
LOGD("data total size of http content: %"G_GINT64_FORMAT, bytes);
- player->http_content_size = (bytes > 0) ? (bytes) : (0);
+ player->http_content_size = (bytes > 0) ? bytes : 0;
}
} else {
/* handling audio clip which has vbr. means duration is keep changing */
- __mmplayer_update_content_attrs(player, ATTR_DURATION);
+ _mmplayer_update_content_attrs(player, ATTR_DURATION);
}
MMPLAYER_FLEAVE();
static gboolean
__mmplayer_eos_timer_cb(gpointer u_data)
{
- mm_player_t* player = NULL;
+ mmplayer_t *player = NULL;
MMHandleType attrs = 0;
int count = 0;
MMPLAYER_RETURN_VAL_IF_FAIL(u_data, FALSE);
- player = (mm_player_t*) u_data;
+ player = (mmplayer_t *)u_data;
attrs = MMPLAYER_GET_ATTRS(player);
mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
if (count == -1) {
gint ret_value = 0;
- ret_value = __mmplayer_gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
+ ret_value = _mmplayer_gst_set_position(player, 0, TRUE);
if (ret_value != MM_ERROR_NONE)
LOGE("seeking to 0 failed in repeat play");
} else {
}
static void
-__mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms)
+__mmplayer_handle_eos_delay(mmplayer_t *player, int delay_in_ms)
{
MMPLAYER_RETURN_IF_FAIL(player);
/* post now if delay is zero */
- if (delay_in_ms == 0 || player->set_mode.pcm_extraction) {
- LOGD("eos delay is zero. posting EOS now\n");
+ if (delay_in_ms == 0 || player->audio_decoded_cb) {
+ LOGD("eos delay is zero. posting EOS now");
MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
- if (player->set_mode.pcm_extraction)
- __mmplayer_cancel_eos_timer(player);
+ if (player->audio_decoded_cb)
+ _mmplayer_cancel_eos_timer(player);
return;
}
/* cancel if existing */
- __mmplayer_cancel_eos_timer(player);
+ _mmplayer_cancel_eos_timer(player);
/* init new timeout */
/* NOTE : consider give high priority to this timer */
- LOGD("posting EOS message after [%d] msec\n", delay_in_ms);
+ LOGD("posting EOS message after [%d] msec", delay_in_ms);
player->eos_timer = g_timeout_add(delay_in_ms,
__mmplayer_eos_timer_cb, player);
/* check timer is valid. if not, send EOS now */
if (player->eos_timer == 0) {
- LOGW("creating timer for delayed EOS has failed. sending EOS now\n");
+ LOGW("creating timer for delayed EOS has failed. sending EOS now");
MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
}
}
-static int __mmplayer_gst_pending_seek(mm_player_t* player)
+static int
+__mmplayer_gst_pending_seek(mmplayer_t *player)
{
- MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
+ mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
if (!player->pending_seek.is_pending) {
- LOGD("pending seek is not reserved. nothing to do.\n");
+ LOGD("pending seek is not reserved. nothing to do.");
return ret;
}
current_state = MMPLAYER_CURRENT_STATE(player);
if (current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING) {
- LOGW("try to pending seek in %s state, try next time. \n",
+ LOGW("try to pending seek in %s state, try next time. ",
MMPLAYER_STATE_GET_NAME(current_state));
return ret;
}
- LOGD("trying to play from(%"G_GINT64_FORMAT") pending position\n", player->pending_seek.pos);
+ LOGD("trying to play from(%"G_GINT64_FORMAT") pending position", player->pending_seek.pos);
- ret = __mmplayer_gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, FALSE);
+ ret = _mmplayer_gst_set_position(player, player->pending_seek.pos, FALSE);
+ if (ret != MM_ERROR_NONE)
+ LOGE("failed to seek pending postion. just keep staying current position.");
- if (MM_ERROR_NONE != ret)
- LOGE("failed to seek pending postion. just keep staying current position.\n");
-
- player->pending_seek.is_pending = FALSE;
+ player->pending_seek.is_pending = false;
MMPLAYER_FLEAVE();
}
static void
-__mmplayer_gst_handle_async(mm_player_t* player, gboolean async, enum MMPlayerSinkType type)
+__mmplayer_gst_set_async(mmplayer_t *player, gboolean async, enum mmplayer_sink_type type)
{
- MMPlayerGstElement *videobin = NULL, *audiobin = NULL, *textbin = NULL;
+ mmplayer_gst_element_t *videobin = NULL, *audiobin = NULL, *textbin = NULL;
MMPLAYER_RETURN_IF_FAIL(player && player->pipeline);
}
static void
-__mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
+__mmplayer_drop_subtitle(mmplayer_t *player, gboolean is_drop)
{
- MMPlayerGstElement *textbin;
+ mmplayer_gst_element_t *textbin;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player &&
textbin = player->pipeline->textbin;
if (is_drop) {
- LOGD("Drop subtitle text after getting EOS\n");
+ LOGD("Drop subtitle text after getting EOS");
- __mmplayer_gst_handle_async(player, FALSE, MMPLAYER_TEXT_SINK);
+ __mmplayer_gst_set_async(player, FALSE, MMPLAYER_TEXT_SINK);
g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
player->is_subtitle_force_drop = TRUE;
} else {
if (player->is_subtitle_force_drop == TRUE) {
- LOGD("Enable subtitle data path without drop\n");
+ LOGD("Enable subtitle data path without drop");
g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
- __mmplayer_gst_handle_async(player, TRUE, MMPLAYER_TEXT_SINK);
+ __mmplayer_gst_set_async(player, TRUE, MMPLAYER_TEXT_SINK);
LOGD("non-connected with external display");
}
static void
-__mmplayer_gst_handle_eos_message(mm_player_t* player, GstMessage *msg)
+__mmplayer_gst_handle_eos_message(mmplayer_t *player, GstMessage *msg)
{
MMHandleType attrs = 0;
gint count = 0;
return;
}
- if (player->pipeline) {
- if (player->pipeline->textbin)
- __mmplayer_drop_subtitle(player, TRUE);
-
- if ((player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex)) {
- GstPad *pad = NULL;
-
- pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
-
- LOGD("release audio callback");
-
- /* release audio callback */
- gst_pad_remove_probe(pad, player->audio_cb_probe_id);
- player->audio_cb_probe_id = 0;
- /* audio callback should be free because it can be called even though probe remove.*/
- player->audio_stream_cb = NULL;
- player->audio_stream_cb_user_param = NULL;
+ if (player->pipeline && player->pipeline->textbin)
+ __mmplayer_drop_subtitle(player, TRUE);
- }
- }
- if ((player->audio_stream_render_cb_ex) && (!player->audio_stream_sink_sync))
- __mmplayer_audio_stream_clear_buffer(player, TRUE);
+ if ((player->audio_decoded_cb) && (player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK))
+ _mmplayer_audio_stream_clear_buffer(player, TRUE);
/* rewind if repeat count is greater then zero */
/* get play count */
attrs = MMPLAYER_GET_ATTRS(player);
-
if (attrs) {
mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
if (count == -1 || player->playback_rate < 0.0) /* default value is 1 */ {
if (player->playback_rate < 0.0) {
player->resumed_by_rewind = TRUE;
- _mmplayer_set_mute((MMHandleType)player, 0);
+ _mmplayer_set_mute((MMHandleType)player, false);
MMPLAYER_POST_MSG(player, MM_MESSAGE_RESUMED_BY_REW, NULL);
}
}
static void
-__mmplayer_gst_handle_error_message(mm_player_t* player, GstMessage *msg)
+__mmplayer_gst_handle_error_message(mmplayer_t *player, GstMessage *msg)
{
GError *error = NULL;
- gchar* debug = NULL;
+ gchar *debug = NULL;
MMPLAYER_FENTER();
__mmplayer_handle_streaming_error(player, msg);
/* dump state of all element */
- __mmplayer_dump_pipeline_state(player);
+ _mmplayer_dump_pipeline_state(player);
} else {
/* traslate gst error code to msl error code. then post it
* to application if needed
LOGE("error debug : %s", debug);
}
- if (MMPLAYER_IS_HTTP_PD(player))
- _mmplayer_unrealize_pd_downloader((MMHandleType)player);
-
MMPLAYER_FREEIF(debug);
g_error_free(error);
}
static void
-__mmplayer_gst_handle_buffering_message(mm_player_t* player, GstMessage *msg)
+__mmplayer_gst_handle_buffering_message(mmplayer_t *player, GstMessage *msg)
{
MMMessageParamType msg_param = {0, };
int bRet = MM_ERROR_NONE;
return;
}
- if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
- if (!MMPLAYER_CMD_TRYLOCK(player)) {
- /* skip the playback control by buffering msg while user request is handled. */
- gint per = 0;
-
- LOGW("[PD mode] can't get cmd lock, only post buffering msg");
-
- gst_message_parse_buffering(msg, &per);
- LOGD("[PD mode][%s] buffering %d %%....", GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)), per);
-
- msg_param.connection.buffering = per;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
- return;
- }
- } else {
- MMPLAYER_CMD_LOCK(player);
- }
+ MMPLAYER_CMD_LOCK(player);
if (!player->streamer) {
LOGW("Pipeline is shutting down");
gst_message_parse_buffering(msg, &buffer_percent);
if (buffer_percent == MAX_BUFFER_PERCENT) {
- LOGD("Ignored all the previous buffering msg!(got %d%%)\n", buffer_percent);
+ LOGD("Ignored all the previous buffering msg!(got %d%%)", buffer_percent);
+ __mmplayer_update_buffer_setting(player, NULL); /* update buffering size for next buffering */
player->streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
}
MMPLAYER_CMD_UNLOCK(player);
}
} else if (bRet == MM_ERROR_PLAYER_INVALID_STATE) {
if (!player->streamer) {
- LOGW("player->streamer is NULL, so discarding the buffering percent update\n");
+ LOGW("player->streamer is NULL, so discarding the buffering percent update");
MMPLAYER_CMD_UNLOCK(player);
return;
}
if ((MMPLAYER_IS_LIVE_STREAMING(player)) && (MMPLAYER_IS_RTSP_STREAMING(player))) {
- LOGD("player->last_position=%"G_GINT64_FORMAT" , player->streamer->buffering_percent=%d \n",
+ LOGD("player->last_position=%"G_GINT64_FORMAT" , player->streamer->buffering_percent=%d",
GST_TIME_AS_SECONDS(player->last_position), player->streamer->buffering_percent);
if ((GST_TIME_AS_SECONDS(player->last_position) <= 0) && (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)) {
msg_param.connection.buffering = player->streamer->buffering_percent;
MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
} else {
- LOGD("Not updating Buffering Message for Live RTSP case !!!\n");
+ LOGD("Not updating Buffering Message for Live RTSP case !!!");
}
} else {
msg_param.connection.buffering = player->streamer->buffering_percent;
}
static void
-__mmplayer_gst_handle_state_message(mm_player_t* player, GstMessage *msg)
+__mmplayer_gst_handle_state_message(mmplayer_t *player, GstMessage *msg)
{
- MMPlayerGstElement *mainbin;
+ mmplayer_gst_element_t *mainbin;
const GValue *voldstate, *vnewstate, *vpending;
GstState oldstate = GST_STATE_NULL;
GstState newstate = GST_STATE_NULL;
int retVal = MM_ERROR_NONE;
LOGD("trying to play from (%"G_GINT64_FORMAT") pending position", player->pending_seek.pos);
- retVal = __mmplayer_gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, TRUE);
+ retVal = _mmplayer_gst_set_position(player, player->pending_seek.pos, TRUE);
if (MM_ERROR_NONE != retVal)
LOGE("failed to seek pending postion. just keep staying current position.");
- player->pending_seek.is_pending = FALSE;
+ player->pending_seek.is_pending = false;
}
}
{
gboolean prepare_async = FALSE;
- if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
- __mmplayer_configure_audio_callback(player);
-
if (!player->sent_bos && oldstate == GST_STATE_READY) {
// managed prepare async case
mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
- __mm_player_streaming_set_content_bitrate(player->streamer,
+ _mm_player_streaming_set_content_bitrate(player->streamer,
player->total_maximum_bitrate, player->total_bitrate);
if (player->pending_seek.is_pending) {
}
if (player->gapless.stream_changed) {
- __mmplayer_update_content_attrs(player, ATTR_ALL);
+ _mmplayer_update_content_attrs(player, ATTR_ALL);
player->gapless.stream_changed = FALSE;
}
}
static void
-__mmplayer_gst_handle_element_message(mm_player_t* player, GstMessage *msg)
+__mmplayer_gst_handle_element_message(mmplayer_t *player, GstMessage *msg)
{
const gchar *structure_name;
gint count = 0, idx = 0;
- MMHandleType attrs = 0;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("Failed to get content attribute");
- return;
- }
-
if (gst_message_get_structure(msg) == NULL)
return;
count = g_list_length(player->adaptive_info.var_list);
if (count > 0) {
- VariantData *temp = NULL;
+ stream_variant_t *temp = NULL;
/* print out for debug */
LOGD("num of variant_info %d", count);
gint extra_num_buffers = 0;
if (gst_structure_get_int(gst_message_get_structure(msg), "num_buffers", &num_buffers)) {
- player->video_num_buffers = num_buffers;
- LOGD("video_num_buffers : %d", player->video_num_buffers);
+ LOGD("video_num_buffers : %d", num_buffers);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_BUFFER_TOTAL_SIZE, num_buffers, NULL);
}
if (gst_structure_get_int(gst_message_get_structure(msg), "extra_num_buffers", &extra_num_buffers)) {
- player->video_extra_num_buffers = extra_num_buffers;
LOGD("num_of_vout_extra num buffers : %d", extra_num_buffers);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_BUFFER_EXTRA_SIZE, extra_num_buffers, NULL);
}
return;
}
- if (!strcmp(structure_name, "Language_list")) {
- const GValue *lang_list = NULL;
- lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
- if (lang_list != NULL) {
- count = g_list_length((GList *)g_value_get_pointer(lang_list));
- if (count > 1)
- LOGD("Total audio tracks(from parser) = %d \n", count);
- }
- }
-
- if (!strcmp(structure_name, "Ext_Sub_Language_List")) {
- const GValue *lang_list = NULL;
- MMPlayerLangStruct *temp = NULL;
-
- lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
- if (lang_list != NULL) {
- count = g_list_length((GList *)g_value_get_pointer(lang_list));
- if (count) {
- MMPLAYER_SUBTITLE_INFO_LOCK(player);
- player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
- mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
- if (mmf_attrs_commit(attrs))
- LOGE("failed to commit.\n");
- LOGD("Total subtitle tracks = %d \n", count);
-
- while (count) {
- temp = g_list_nth_data(player->subtitle_language_list, count - 1);
- if (temp)
- LOGD("value of lang_key is %s and lang_code is %s",
- temp->language_key, temp->language_code);
- count--;
- }
- MMPLAYER_SUBTITLE_INFO_SIGNAL(player);
- MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
- }
- }
- }
+ if (!strcmp(structure_name, "Ext_Sub_Language_List"))
+ _mmplayer_track_update_text_attr_info(player, msg);
/* custom message */
if (!strcmp(structure_name, "audio_codec_not_supported")) {
sdp which has contents info is received when rtsp connection is opened.
extract duration ,codec info , resolution from sdp and get it by GstMessage */
if (!strcmp(structure_name, "rtspsrc_properties")) {
-
gchar *audio_codec = NULL;
gchar *video_codec = NULL;
gchar *video_frame_size = NULL;
- gst_structure_get(gst_message_get_structure(msg), "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL);
+ gst_structure_get(gst_message_get_structure(msg),
+ "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL);
LOGD("rtsp duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(player->duration));
- player->streaming_type = __mmplayer_get_stream_service_type(player);
+ player->streaming_type = _mmplayer_get_stream_service_type(player);
- gst_structure_get(gst_message_get_structure(msg), "rtsp_audio_codec", G_TYPE_STRING, &audio_codec, NULL);
+ gst_structure_get(gst_message_get_structure(msg),
+ "rtsp_audio_codec", G_TYPE_STRING, &audio_codec, NULL);
LOGD("rtsp_audio_codec : %s", audio_codec);
if (audio_codec)
- mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_audio_codec", audio_codec, strlen(audio_codec), NULL);
- gst_structure_get(gst_message_get_structure(msg), "rtsp_video_codec", G_TYPE_STRING, &video_codec, NULL);
+ gst_structure_get(gst_message_get_structure(msg),
+ "rtsp_video_codec", G_TYPE_STRING, &video_codec, NULL);
LOGD("rtsp_video_codec : %s", video_codec);
if (video_codec)
- mm_attrs_set_string_by_name(player->attrs, "content_video_codec", video_codec);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_video_codec", video_codec, strlen(video_codec), NULL);
- gst_structure_get(gst_message_get_structure(msg), "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL);
+ gst_structure_get(gst_message_get_structure(msg),
+ "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL);
LOGD("rtsp_video_frame_size : %s", video_frame_size);
if (video_frame_size) {
-
- char *seperator = strchr(video_frame_size, '-');
- if (seperator) {
-
- char video_width[10] = {0,};
- int frame_size_len = strlen(video_frame_size);
- int separtor_len = strlen(seperator);
-
- strncpy(video_width, video_frame_size, (frame_size_len - separtor_len));
- mm_attrs_set_int_by_name(attrs, "content_video_width", atoi(video_width));
-
- seperator++;
- mm_attrs_set_int_by_name(attrs, "content_video_height", atoi(seperator));
- }
+ gchar **res_str = g_strsplit(video_frame_size, "-", 0);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_WIDTH, atoi(res_str[0]),
+ MM_PLAYER_VIDEO_HEIGHT, atoi(res_str[1]),
+ NULL);
+ g_strfreev(res_str);
}
-
- if (mmf_attrs_commit(attrs))
- LOGE("failed to commit.\n");
}
MMPLAYER_FLEAVE();
}
static void
-__mmplayer_gst_handle_async_done_message(mm_player_t* player, GstMessage *msg)
+__mmplayer_gst_handle_async_done_message(mmplayer_t *player, GstMessage *msg)
{
- MMPlayerGstElement *mainbin;
+ mmplayer_gst_element_t *mainbin;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
gst_query_parse_buffering_percent(query, &busy, &percent);
gst_query_unref(query);
- LOGD("buffered percent(%s): %d\n",
+ LOGD("buffered percent(%s): %d",
GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
}
}
static void
+__mmplayer_print_tag_foreach(const GstTagList *tags, const gchar *tag, gpointer user_data)
+{
+ GValue val = { 0, };
+ gchar *str = NULL;
+ guint indent = GPOINTER_TO_UINT(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 * indent, " ", 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(MMPLAYER_TAG_INDENT));
+ 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",
+ gst_stream_get_stream_id(stream), 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);
+ }
+
+ if (g_str_equal (pspec->name, "tags")) {
+ GstTagList *tags = gst_stream_get_tags(stream);
+ if (tags) {
+ LOGD (" tags:\n");
+ gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(MMPLAYER_TAG_INDENT));
+ gst_tag_list_unref(tags);
+ }
+ }
+}
+
+static void
__mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data)
{
- mm_player_t* player = (mm_player_t*)(data);
+ mmplayer_t *player = (mmplayer_t *)(data);
MMPLAYER_RETURN_IF_FAIL(player);
MMPLAYER_RETURN_IF_FAIL(msg && GST_IS_MESSAGE(msg));
switch (GST_MESSAGE_TYPE(msg)) {
case GST_MESSAGE_UNKNOWN:
- LOGD("unknown message received\n");
+ LOGD("unknown message received");
break;
case GST_MESSAGE_EOS:
break;
case GST_MESSAGE_ERROR:
+ _mmplayer_set_reconfigure_state(player, FALSE);
__mmplayer_gst_handle_error_message(player, msg);
break;
case GST_MESSAGE_WARNING:
{
- char* debug = NULL;
- GError* error = NULL;
+ char *debug = NULL;
+ GError *error = NULL;
gst_message_parse_warning(msg, &error, &debug);
- LOGD("warning : %s\n", error->message);
- LOGD("debug : %s\n", debug);
+ LOGD("warning : %s", error->message);
+ LOGD("debug : %s", debug);
MMPLAYER_POST_MSG(player, MM_MESSAGE_WARNING, NULL);
case GST_MESSAGE_TAG:
{
- LOGD("GST_MESSAGE_TAG\n");
+ LOGD("GST_MESSAGE_TAG");
if (!__mmplayer_gst_extract_tag_from_msg(player, msg))
- LOGW("failed to extract tags from gstmessage\n");
+ LOGW("failed to extract tags from gstmessage");
}
break;
gboolean need_new_clock = FALSE;
gst_message_parse_clock_lost(msg, &clock);
- LOGD("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
+ LOGD("GST_MESSAGE_CLOCK_LOST : %s", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
if (!player->videodec_linked)
need_new_clock = TRUE;
need_new_clock = TRUE;
if (need_new_clock) {
- LOGD("Provide clock is TRUE, do pause->resume\n");
- __mmplayer_gst_pause(player, FALSE);
- __mmplayer_gst_resume(player, FALSE);
+ LOGD("Provide clock is TRUE, do pause->resume");
+ _mmplayer_gst_pause(player, FALSE);
+ _mmplayer_gst_resume(player, FALSE);
}
}
break;
{
GstClock *clock = NULL;
gst_message_parse_new_clock(msg, &clock);
- LOGD("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
+ LOGD("GST_MESSAGE_NEW_CLOCK : %s", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
}
break;
case GST_MESSAGE_DURATION_CHANGED:
{
- LOGD("GST_MESSAGE_DURATION_CHANGED\n");
+ LOGD("GST_MESSAGE_DURATION_CHANGED");
if (!__mmplayer_gst_handle_duration(player, msg))
LOGW("failed to update duration");
}
break;
case GST_MESSAGE_ASYNC_START:
- LOGD("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
+ LOGD("GST_MESSAGE_ASYNC_START : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
break;
case GST_MESSAGE_ASYNC_DONE:
__mmplayer_gst_handle_async_done_message(player, msg);
break;
-
- #if 0 /* delete unnecessary logs */
- case GST_MESSAGE_REQUEST_STATE: LOGD("GST_MESSAGE_REQUEST_STATE\n"); break;
- case GST_MESSAGE_STEP_START: LOGD("GST_MESSAGE_STEP_START\n"); break;
- case GST_MESSAGE_QOS: LOGD("GST_MESSAGE_QOS\n"); break;
- case GST_MESSAGE_PROGRESS: LOGD("GST_MESSAGE_PROGRESS\n"); break;
- case GST_MESSAGE_ANY: LOGD("GST_MESSAGE_ANY\n"); break;
- case GST_MESSAGE_INFO: LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
- case GST_MESSAGE_STATE_DIRTY: LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
- case GST_MESSAGE_STEP_DONE: LOGD("GST_MESSAGE_STEP_DONE\n"); break;
- case GST_MESSAGE_CLOCK_PROVIDE: LOGD("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
- case GST_MESSAGE_STRUCTURE_CHANGE: LOGD("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
- case GST_MESSAGE_STREAM_STATUS: LOGD("GST_MESSAGE_STREAM_STATUS\n"); break;
- case GST_MESSAGE_APPLICATION: LOGD("GST_MESSAGE_APPLICATION\n"); break;
- case GST_MESSAGE_SEGMENT_START: LOGD("GST_MESSAGE_SEGMENT_START\n"); break;
- case GST_MESSAGE_SEGMENT_DONE: LOGD("GST_MESSAGE_SEGMENT_DONE\n"); break;
- case GST_MESSAGE_LATENCY: LOGD("GST_MESSAGE_LATENCY\n"); break;
- #endif
+ case GST_MESSAGE_STREAM_COLLECTION:
+ {
+ GstStreamCollection *collection = NULL;
+ LOGD("GST_MESSAGE_STREAM_COLLECTION : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
+
+ 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)));
+
+ 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;
+ case GST_MESSAGE_STEP_START: LOGD("GST_MESSAGE_STEP_START"); break;
+ case GST_MESSAGE_QOS: LOGD("GST_MESSAGE_QOS"); break;
+ case GST_MESSAGE_PROGRESS: LOGD("GST_MESSAGE_PROGRESS"); break;
+ case GST_MESSAGE_ANY: LOGD("GST_MESSAGE_ANY"); break;
+ case GST_MESSAGE_INFO: LOGD("GST_MESSAGE_STATE_DIRTY"); break;
+ case GST_MESSAGE_STATE_DIRTY: LOGD("GST_MESSAGE_STATE_DIRTY"); break;
+ case GST_MESSAGE_STEP_DONE: LOGD("GST_MESSAGE_STEP_DONE"); break;
+ case GST_MESSAGE_CLOCK_PROVIDE: LOGD("GST_MESSAGE_CLOCK_PROVIDE"); break;
+ case GST_MESSAGE_STRUCTURE_CHANGE: LOGD("GST_MESSAGE_STRUCTURE_CHANGE"); break;
+ case GST_MESSAGE_STREAM_STATUS: LOGD("GST_MESSAGE_STREAM_STATUS"); break;
+ case GST_MESSAGE_APPLICATION: LOGD("GST_MESSAGE_APPLICATION"); break;
+ case GST_MESSAGE_SEGMENT_START: LOGD("GST_MESSAGE_SEGMENT_START"); break;
+ case GST_MESSAGE_SEGMENT_DONE: LOGD("GST_MESSAGE_SEGMENT_DONE"); break;
+ case GST_MESSAGE_LATENCY: LOGD("GST_MESSAGE_LATENCY"); break;
+#endif
default:
break;
}
static GstBusSyncReply
-__mmplayer_gst_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data)
+__mmplayer_gst_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data)
{
- mm_player_t *player = (mm_player_t *)data;
+ mmplayer_t *player = (mmplayer_t *)data;
GstBusSyncReply reply = GST_BUS_DROP;
if (!(player->pipeline && player->pipeline->mainbin)) {
}
switch (GST_MESSAGE_TYPE(message)) {
- case GST_MESSAGE_STATE_CHANGED:
- /* post directly for fast launch */
- if (player->sync_handler) {
- __mmplayer_gst_bus_msg_callback(message, player);
- reply = GST_BUS_DROP;
- } else
- reply = GST_BUS_PASS;
- break;
case GST_MESSAGE_TAG:
__mmplayer_gst_extract_tag_from_msg(player, message);
- #if 0 // debug
+#ifdef __DEBUG__
{
GstTagList *tags = NULL;
gst_message_parse_tag(message, &tags);
if (tags) {
- LOGE("TAGS received from element \"%s\".\n",
+ LOGE("TAGS received from element \"%s\".",
GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
gst_tag_list_foreach(tags, print_tag, NULL);
- gst_tag_list_free(tags);
+ gst_tag_list_unref(tags);
tags = NULL;
}
break;
}
- #endif
+#endif
break;
case GST_MESSAGE_DURATION_CHANGED:
__mmplayer_gst_handle_duration(player, message);
break;
- case GST_MESSAGE_ASYNC_DONE:
+ case GST_MESSAGE_ELEMENT:
+ {
+ const gchar *klass = NULL;
+ klass = gst_element_factory_get_metadata
+ (gst_element_get_factory((GstElement *)message->src), GST_ELEMENT_METADATA_KLASS);
+ if (!klass || !g_strrstr(klass, "Codec/Decoder")) {
+ reply = GST_BUS_PASS;
+ break;
+ }
+ __mmplayer_gst_handle_element_message(player, message);
+ }
+ break;
+ case GST_MESSAGE_ASYNC_DONE:
/* NOTE:Don't call gst_callback directly
* because previous frame can be showed even though this message is received for seek.
*/
__mmplayer_gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data)
{
GstElement *appsrc = element;
- MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
+ mmplayer_input_buffer_t *buf = (mmplayer_input_buffer_t *)user_data;
GstBuffer *buffer = NULL;
GstFlowReturn ret = GST_FLOW_OK;
gint len = size;
GST_BUFFER_OFFSET(buffer) = (guint64)buf->offset;
GST_BUFFER_OFFSET_END(buffer) = (guint64)(buf->offset + len);
- //LOGD("feed buffer %p, offset %u-%u length %u", buffer, buf->offset, (buf->offset+len), len);
+#ifdef __DEBUG__
+ LOGD("feed buffer %p, offset %u-%u length %u", buffer, buf->offset, (buf->offset+len), len);
+#endif
g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
buf->offset += len;
static gboolean
__mmplayer_gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data)
{
- MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
+ mmplayer_input_buffer_t *buf = (mmplayer_input_buffer_t *)user_data;
MMPLAYER_RETURN_VAL_IF_FAIL(buf, FALSE);
void
__mmplayer_gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data)
{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ mmplayer_t *player = (mmplayer_t *)user_data;
+ mmplayer_stream_type_e stream_type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ MMMessageParamType msg_param = {0,};
guint64 current_level_bytes = 0;
MMPLAYER_RETURN_IF_FAIL(player);
- if (g_strrstr(GST_ELEMENT_NAME(element), "audio"))
- type = MM_PLAYER_STREAM_TYPE_AUDIO;
- else if (g_strrstr(GST_ELEMENT_NAME(element), "video"))
- type = MM_PLAYER_STREAM_TYPE_VIDEO;
- else if (g_strrstr(GST_ELEMENT_NAME(element), "subtitle"))
- type = MM_PLAYER_STREAM_TYPE_TEXT;
- else {
- LOGE("can not enter here");
+ if (g_strrstr(GST_ELEMENT_NAME(element), "audio")) {
+ stream_type = MM_PLAYER_STREAM_TYPE_AUDIO;
+ } else if (g_strrstr(GST_ELEMENT_NAME(element), "video")) {
+ stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
+ } else {
+ LOGW("invalid feed-data signal from %s", GST_ELEMENT_NAME(element));
return;
}
g_object_get(G_OBJECT(element), "current-level-bytes", ¤t_level_bytes, NULL);
- LOGI("type: %d, level: %llu", type, current_level_bytes);
+ LOGI("stream type: %d, level: %"G_GUINT64_FORMAT, stream_type, current_level_bytes);
+
+ msg_param.union_type = MM_MSG_UNION_BUFFER_STATUS;
+ msg_param.buffer_status.stream_type = stream_type;
+ msg_param.buffer_status.status = MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN;
+ msg_param.buffer_status.bytes = current_level_bytes;
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
- if (player->media_stream_buffer_status_cb[type])
- player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_PUSH_BUFFER_STATUS, &msg_param);
}
void
__mmplayer_gst_appsrc_enough_data(GstElement *element, gpointer user_data)
{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ mmplayer_t *player = (mmplayer_t *)user_data;
+ mmplayer_stream_type_e stream_type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ MMMessageParamType msg_param = {0,};
guint64 current_level_bytes = 0;
MMPLAYER_RETURN_IF_FAIL(player);
- if (g_strrstr(GST_ELEMENT_NAME(element), "audio"))
- type = MM_PLAYER_STREAM_TYPE_AUDIO;
- else if (g_strrstr(GST_ELEMENT_NAME(element), "video"))
- type = MM_PLAYER_STREAM_TYPE_VIDEO;
- else if (g_strrstr(GST_ELEMENT_NAME(element), "subtitle"))
- type = MM_PLAYER_STREAM_TYPE_TEXT;
- else {
- LOGE("can not enter here");
+ if (g_strrstr(GST_ELEMENT_NAME(element), "audio")) {
+ stream_type = MM_PLAYER_STREAM_TYPE_AUDIO;
+ } else if (g_strrstr(GST_ELEMENT_NAME(element), "video")) {
+ stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
+ } else {
+ LOGW("invalid enough-data signal from %s", GST_ELEMENT_NAME(element));
return;
}
- LOGI("type: %d, buffer is full", type);
-
g_object_get(G_OBJECT(element), "current-level-bytes", ¤t_level_bytes, NULL);
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
+ LOGI("stream type: %d, level: %"G_GUINT64_FORMAT, stream_type, current_level_bytes);
- if (player->media_stream_buffer_status_cb[type])
- player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
+ msg_param.union_type = MM_MSG_UNION_BUFFER_STATUS;
+ msg_param.buffer_status.stream_type = stream_type;
+ msg_param.buffer_status.status = MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW;
+ msg_param.buffer_status.bytes = current_level_bytes;
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_PUSH_BUFFER_STATUS, &msg_param);
}
gboolean
-__mmplayer_gst_appsrc_seek_data(GstElement * element, guint64 position, gpointer user_data)
+__mmplayer_gst_appsrc_seek_data(GstElement *element, guint64 position, gpointer user_data)
{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ mmplayer_t *player = (mmplayer_t *)user_data;
+ mmplayer_stream_type_e stream_type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ MMMessageParamType msg_param = {0,};
MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
- if (g_strrstr(GST_ELEMENT_NAME(element), "audio"))
- type = MM_PLAYER_STREAM_TYPE_AUDIO;
- else if (g_strrstr(GST_ELEMENT_NAME(element), "video"))
- type = MM_PLAYER_STREAM_TYPE_VIDEO;
- else if (g_strrstr(GST_ELEMENT_NAME(element), "subtitle"))
- type = MM_PLAYER_STREAM_TYPE_TEXT;
- else {
- LOGE("can not enter here");
+ if (g_strrstr(GST_ELEMENT_NAME(element), "audio")) {
+ stream_type = MM_PLAYER_STREAM_TYPE_AUDIO;
+ } else if (g_strrstr(GST_ELEMENT_NAME(element), "video")) {
+ stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
+ } else {
+ LOGW("invalid seek-data signal from %s", GST_ELEMENT_NAME(element));
return TRUE;
}
- LOGD("type: %d, pos: %llu", type, position);
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
+ LOGD("stream type: %d, pos: %"G_GUINT64_FORMAT, stream_type, position);
+
+ msg_param.union_type = MM_MSG_UNION_SEEK_DATA;
+ msg_param.seek_data.stream_type = stream_type;
+ msg_param.seek_data.offset = position;
- if (player->media_stream_seek_data_cb[type])
- player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_PUSH_BUFFER_SEEK_DATA, &msg_param);
return TRUE;
}
static gboolean
-__mmplayer_gst_create_es_decoder(mm_player_t *player, MMPlayerStreamType type, GstPad* srcpad)
+__mmplayer_gst_create_es_decoder(mmplayer_t *player, mmplayer_stream_type_e type, GstPad *srcpad)
{
#define MAX_LEN_NAME 20
gboolean ret = FALSE;
GstPad *sinkpad = NULL;
gchar *prefix = NULL;
- gchar dec_name[MAX_LEN_NAME] = {0};
- enum MainElementID elem_id = MMPLAYER_M_NUM;
+ gchar dec_name[MAX_LEN_NAME] = {0, };
+ main_element_id_e elem_id = MMPLAYER_M_NUM;
- MMPlayerGstElement *mainbin = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
GstElement *decodebin = NULL;
GstCaps *dec_caps = NULL;
mainbin[elem_id].gst = decodebin;
/* raw pad handling signal */
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
- G_CALLBACK(__mmplayer_gst_decode_pad_added), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
+ G_CALLBACK(_mmplayer_gst_decode_pad_added), (gpointer)player);
/* This signal is emitted whenever decodebin finds a new stream. It is emitted
before looking for any elements that can handle that stream.*/
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
- G_CALLBACK(__mmplayer_gst_decode_autoplug_select), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
+ G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
+
+ if (player->need_video_dec_sorting || player->need_audio_dec_sorting)
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
+ G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
/* This signal is emitted when a element is added to the bin.*/
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
- G_CALLBACK(__mmplayer_gst_element_added), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
+ G_CALLBACK(_mmplayer_gst_element_added), (gpointer)player);
if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
LOGE("failed to add new decodebin");
dec_caps = gst_pad_query_caps(srcpad, NULL);
if (dec_caps) {
- //LOGD("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
+#ifdef __DEBUG__
+ LOGD("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
+#endif
g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
gst_caps_unref(dec_caps);
}
}
static gboolean
-__mmplayer_gst_create_es_path(mm_player_t* player, MMPlayerStreamType type, GstCaps* caps)
+__mmplayer_gst_create_es_path(mmplayer_t *player, mmplayer_stream_type_e type, GstCaps *caps)
{
#define MAX_LEN_NAME 20
- MMPlayerGstElement *mainbin = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
gchar *prefix = NULL;
- enum MainElementID src_id = MMPLAYER_M_NUM, queue_id = MMPLAYER_M_NUM;
+ main_element_id_e src_id = MMPLAYER_M_NUM, queue_id = MMPLAYER_M_NUM;
- gchar src_name[MAX_LEN_NAME] = {0}, queue_name[MAX_LEN_NAME] = {0};
+ gchar src_name[MAX_LEN_NAME] = {0, }, queue_name[MAX_LEN_NAME] = {0, };
GstElement *src = NULL, *queue = NULL;
GstPad *srcpad = NULL;
/*Fix Seek External Demuxer: set audio and video appsrc as seekable */
gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(src), GST_APP_STREAM_TYPE_SEEKABLE);
- __mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
+ _mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
G_CALLBACK(__mmplayer_gst_appsrc_seek_data), (gpointer)player);
- __mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
+ _mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
G_CALLBACK(__mmplayer_gst_appsrc_feed_data), (gpointer)player);
- __mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
+ _mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
G_CALLBACK(__mmplayer_gst_appsrc_enough_data), (gpointer)player);
/* create queue */
}
if (type == MM_PLAYER_STREAM_TYPE_TEXT) {
- __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[queue_id].gst, "src"), caps);
+ _mmplayer_gst_create_decoder(player, srcpad, caps);
} else {
if (!__mmplayer_gst_create_es_decoder(player, type, srcpad)) {
LOGE("failed to create decoder");
__mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data)
{
GstPad *sinkpad = NULL;
- GstCaps* caps = NULL;
- GstElement* new_element = NULL;
- GstStructure* str = NULL;
- const gchar* name = NULL;
+ GstCaps *caps = NULL;
+ GstElement *new_element = NULL;
+ GstStructure *str = NULL;
+ const gchar *name = NULL;
- mm_player_t* player = (mm_player_t*) data;
+ mmplayer_t *player = (mmplayer_t *)data;
MMPLAYER_FENTER();
player->pipeline &&
player->pipeline->mainbin);
-
/* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
* num_dynamic_pad will decreased after creating a sinkbin.
*/
player->num_dynamic_pad++;
- LOGD("stream count inc : %d\n", player->num_dynamic_pad);
+ LOGD("stream count inc : %d", player->num_dynamic_pad);
caps = gst_pad_query_caps(pad, NULL);
-
MMPLAYER_CHECK_NULL(caps);
- /* clear previous result*/
- player->have_dynamic_pad = FALSE;
-
str = gst_caps_get_structure(caps, 0);
-
- if (!str) {
- LOGE("cannot get structure from caps.\n");
- goto ERROR;
- }
-
- name = gst_structure_get_name(str);
+ name = gst_structure_get_string(str, "media");
if (!name) {
- LOGE("cannot get mimetype from structure.\n");
+ LOGE("cannot get mimetype from structure.");
goto ERROR;
}
gint stype = 0;
mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
- if (stype == MM_DISPLAY_SURFACE_NULL || stype == MM_DISPLAY_SURFACE_REMOTE) {
+ if ((stype == MM_DISPLAY_SURFACE_NULL) && (!player->set_mode.video_export)) {
if (player->v_stream_caps) {
gst_caps_unref(player->v_stream_caps);
player->v_stream_caps = NULL;
}
}
- /* clear previous result*/
- player->have_dynamic_pad = FALSE;
-
- if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
+ if (!_mmplayer_gst_create_decoder(player, pad, caps)) {
LOGE("failed to autoplug for caps");
goto ERROR;
}
- /* check if there's dynamic pad*/
- if (player->have_dynamic_pad) {
- LOGE("using pad caps assums there's no dynamic pad !\n");
- goto ERROR;
- }
-
gst_caps_unref(caps);
caps = NULL;
/* excute new_element if created*/
if (new_element) {
- LOGD("adding new element to pipeline\n");
+ LOGD("adding new element to pipeline");
/* set state to READY before add to bin */
MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
/* add new element to the pipeline */
if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
- LOGE("failed to add autoplug element to bin\n");
+ LOGE("failed to add autoplug element to bin");
goto ERROR;
}
/* get pad from element */
sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
if (!sinkpad) {
- LOGE("failed to get sinkpad from autoplug element\n");
+ LOGE("failed to get sinkpad from autoplug element");
goto ERROR;
}
/* link it */
if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGE("failed to link autoplug element\n");
+ LOGE("failed to link autoplug element");
goto ERROR;
}
static void
__mmplayer_gst_rtp_no_more_pads(GstElement *element, gpointer data)
{
- mm_player_t* player = (mm_player_t*) data;
+ mmplayer_t *player = (mmplayer_t *)data;
MMPLAYER_FENTER();
/* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
- * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
- * num_dynamic_pad. and this is no-more-pad situation which means no more pad will be added.
- * So we can say this. if num_dynamic_pad is zero, it must be one of followings
-
- * [1] audio and video will be dumped with filesink.
- * [2] autoplugging is done by just using pad caps.
- * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
- * and the video will be dumped via filesink.
- */
+ * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
+ * num_dynamic_pad. and this is no-more-pad situation which means no more pad will be added.
+ * So we can say this. if num_dynamic_pad is zero, it must be one of followings
+
+ * [1] audio and video will be dumped with filesink.
+ * [2] autoplugging is done by just using pad caps.
+ * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
+ * and the video will be dumped via filesink.
+ */
if (player->num_dynamic_pad == 0) {
- LOGD("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
+ LOGD("it seems pad caps is directely used for autoplugging. removing fakesink now");
- if (!__mmplayer_gst_remove_fakesink(player,
+ if (!_mmplayer_gst_remove_fakesink(player,
&player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]))
- /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
+ /* NOTE : _mmplayer_pipeline_complete() can be called several time. because
* signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
* source element are not same. To overcome this situation, this function will called
* several places and several times. Therefore, this is not an error case.
MMPLAYER_FLEAVE();
}
-static GstElement*
-__mmplayer_gst_create_rtsp_src(mm_player_t* player)
+static GstElement *
+__mmplayer_gst_make_rtsp_src(mmplayer_t *player)
{
- GstElement* element = NULL;
+ GstElement *element = NULL;
gchar *user_agent = NULL;
MMHandleType attrs = 0;
if (user_agent)
g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
- __mmplayer_add_signal_connection(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
+ _mmplayer_add_signal_connection(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
G_CALLBACK(__mmplayer_gst_rtp_dynamic_pad), (gpointer)player);
- __mmplayer_add_signal_connection(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
+ _mmplayer_add_signal_connection(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
G_CALLBACK(__mmplayer_gst_rtp_no_more_pads), (gpointer)player);
MMPLAYER_FLEAVE();
return element;
}
-static GstElement*
-__mmplayer_gst_create_http_src(mm_player_t* player)
+void __mmplayer_http_src_setup(GstElement *source, gpointer data)
+{
+#define HTTP_SOURCE_BLOCK_SIZE (64 * 1024)
+
+ mmplayer_t *player = (mmplayer_t *)data;
+ MMHandleType attrs = 0;
+ gchar *user_agent, *cookies, **cookie_list;
+ gint http_timeout = DEFAULT_HTTP_TIMEOUT;
+ user_agent = cookies = NULL;
+ cookie_list = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player);
+
+ LOGD("source element %s", GST_ELEMENT_NAME(source));
+
+ /* get profile attribute */
+ attrs = MMPLAYER_GET_ATTRS(player);
+ if (!attrs) {
+ LOGE("failed to get content attribute");
+ return;
+ }
+
+ /* get attribute */
+ mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
+ mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
+
+ if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT)
+ http_timeout = player->ini.http_timeout;
+
+ /* get attribute */
+ SECURE_LOGD("cookies : %s", cookies);
+ SECURE_LOGD("user_agent : %s", user_agent);
+ LOGD("timeout : %d", http_timeout);
+
+ /* setting property to streaming source */
+ g_object_set(G_OBJECT(source), "timeout", http_timeout, "blocksize", (unsigned long)(HTTP_SOURCE_BLOCK_SIZE), NULL);
+
+ /* parsing cookies */
+ if ((cookie_list = _mmplayer_get_cookie_list((const char *)cookies))) {
+ g_object_set(G_OBJECT(source), "cookies", cookie_list, NULL);
+ g_strfreev(cookie_list);
+ }
+
+ if (user_agent)
+ g_object_set(G_OBJECT(source), "user-agent", user_agent, NULL);
+
+ MMPLAYER_FLEAVE();
+ return;
+}
+
+static void
+__mmplayer_gst_found_source(GObject *object, GObject *orig, GParamSpec *pspec, gpointer data)
+{
+ mmplayer_t *player = (mmplayer_t *)data;
+ GstElement *source = NULL;
+
+ MMPLAYER_FENTER();
+ LOGD("%s >> %s", GST_ELEMENT_NAME(object), pspec->name);
+
+ g_object_get(orig, pspec->name, &source, NULL);
+
+ 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(source, data);
+ } else if (MMPLAYER_IS_RTSP_STREAMING(player)) {
+ gchar *user_agent = NULL;
+
+ /* get attribute */
+ mm_attrs_get_string_by_name(player->attrs, "streaming_user_agent", &user_agent);
+
+ SECURE_LOGD("user_agent : %s", user_agent);
+
+ /* setting property to streaming source */
+ if (user_agent)
+ g_object_set(G_OBJECT(source), "user-agent", user_agent, NULL);
+ } else if (MMPLAYER_IS_SMOOTH_STREAMING(player)) {
+ g_object_set(G_OBJECT(source), "timeout", DEFAULT_HTTP_TIMEOUT, NULL);
+ } else if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) {
+ g_object_set(source, "stream-type", GST_APP_STREAM_TYPE_RANDOM_ACCESS,
+ "size", (gint64)player->profile.input_mem.len, "blocksize", 20480, NULL);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(source), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
+ G_CALLBACK(__mmplayer_gst_appsrc_seek_data_mem), (gpointer)&player->profile.input_mem);
+ _mmplayer_add_signal_connection(player, G_OBJECT(source), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
+ G_CALLBACK(__mmplayer_gst_appsrc_feed_data_mem), (gpointer)&player->profile.input_mem);
+ }
+ MMPLAYER_FLEAVE();
+}
+
+static gint
+__mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection,
+ GstStream * stream, gpointer data)
+{
+ gint ret = 0; /* 1: select, 0: skip, -1: depends on decodebin */
+ GstStreamType stype = gst_stream_get_stream_type(stream);
+ mmplayer_t *player = (mmplayer_t *)data;
+ mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_MAX;
+ GstCaps *caps = gst_stream_get_caps(stream);
+ gchar *caps_str = NULL;
+
+ LOGD("Stream type %s flags 0x%x",
+ gst_stream_type_get_name(stype),
+ gst_stream_get_stream_flags(stream));
+ LOGD(" ID: %s", gst_stream_get_stream_id(stream));
+
+ if (caps) {
+ caps_str = gst_caps_to_string(caps);
+ LOGD(" caps: %s", caps_str);
+ }
+
+ switch (stype) {
+ case GST_STREAM_TYPE_AUDIO:
+ {
+ GstStructure *caps_structure = NULL;
+ gint samplerate = 0;
+ gint channels = 0;
+
+ type = MM_PLAYER_TRACK_TYPE_AUDIO;
+
+ if (caps) {
+ caps_structure = gst_caps_get_structure(caps, 0);
+ gst_structure_get_int(caps_structure, "rate", &samplerate);
+ gst_structure_get_int(caps_structure, "channels", &channels);
+
+ if (channels > 0 && samplerate == 0) {
+ LOGW("Skip corrupted audio stream");
+ goto EXIT;
+ }
+
+ if (g_strrstr(caps_str, "mobile-xmf"))
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL);
+ }
+ break;
+ }
+ case GST_STREAM_TYPE_VIDEO:
+ {
+ GstStructure *caps_structure = NULL;
+ gint stype = 0;
+ gint width = 0;
+
+ type = MM_PLAYER_TRACK_TYPE_VIDEO;
+
+ /* do not support multi track video */
+ if (player->track[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num >= 1)
+ goto EXIT;
+
+ mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
+
+ /* don't make video because of not required */
+ if ((stype == MM_DISPLAY_SURFACE_NULL) &&
+ (!player->set_mode.video_export)) {
+ LOGD("no need video decoding, skip video stream");
+ goto EXIT;
+ }
+
+ if (caps) {
+ caps_structure = gst_caps_get_structure(caps, 0);
+ gst_structure_get_int(caps_structure, "width", &width);
+
+ if (width != 0) {
+ if (player->v_stream_caps) {
+ gst_caps_unref(player->v_stream_caps);
+ player->v_stream_caps = NULL;
+ }
+
+ player->v_stream_caps = gst_caps_copy(caps);
+ MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
+ }
+ }
+ break;
+ }
+ case GST_STREAM_TYPE_TEXT:
+ type = MM_PLAYER_TRACK_TYPE_TEXT;
+ break;
+ default:
+ LOGW("Skip not supported stream type");
+ goto EXIT;
+ }
+
+ _mmplayer_track_update_stream(player, type, stream);
+
+ if (player->track[type].active_track_index == (player->track[type].total_track_num - 1)) {
+ LOGD("select this stream, active idx : %d", player->track[type].active_track_index);
+ if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
+ _mmplayer_set_audio_attrs(player, caps);
+ ret = 1;
+ }
+
+EXIT:
+ g_free(caps_str);
+ if (caps)
+ gst_caps_unref(caps);
+
+ LOGD("ret %d", ret);
+ return ret;
+}
+
+static gboolean
+__mmplayer_gst_decode_request_resource(GstElement * uridecodebin, GstStreamCollection * collection,
+ GstStream * stream, gpointer data)
+{
+ mmplayer_t *player = (mmplayer_t *)data;
+ GstStreamType stype = gst_stream_get_stream_type(stream);
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
+
+ LOGD("stream type %s", gst_stream_type_get_name(stype));
+
+ /* public does not support audio hw decoder at the moment */
+
+ if (player->hw_resource[MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER] != NULL) {
+ LOGW("video decoder resource is already acquired, skip it.");
+ return TRUE;
+ }
+
+ if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+ LOGE("failed to acquire video decoder resource");
+ return FALSE;
+ }
+ player->interrupted_by_resource = FALSE;
+ MMPLAYER_FLEAVE();
+ return TRUE;
+}
+
+static void
+__mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *element, gpointer data)
+{
+ gchar *factory_name = NULL;
+ mmplayer_t *player = (mmplayer_t *)data;
+ mmplayer_gst_element_t *mainbin = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
+
+ factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
+ mainbin = player->pipeline->mainbin;
+
+ LOGD("%s > %s > %s : %s", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(child),
+ factory_name, GST_ELEMENT_NAME(element));
+
+ /* keep the first typefind reference only */
+ 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;
+ }
+
+ if ((MMPLAYER_IS_STREAMING(player)) && (!MMPLAYER_IS_RTSP_STREAMING(player))) {
+ /* update queue2 setting */
+ if (g_strrstr(factory_name, "queue2") && (!mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
+ gint64 dur_bytes = 0L;
+ muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
+
+ mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
+ mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
+
+ if (!gst_element_query_duration(mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
+ LOGW("failed to get duration from source %s", GST_ELEMENT_NAME(mainbin[MMPLAYER_M_SRC].gst));
+
+ LOGD("type %s, dur_bytes = %"G_GINT64_FORMAT, player->type, dur_bytes);
+ /* NOTE : in case of ts streaming, player could not get the correct duration info *
+ * skip the pull mode(file or ring buffering) setting. */
+ if (dur_bytes > 0) {
+ if ((!g_strrstr(player->type, "video/mpegts")) && (!g_strrstr(player->type, "application/x-hls"))) {
+ type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
+ player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
+ }
+ } else {
+ dur_bytes = 0;
+ }
+
+ _mm_player_streaming_set_queue2(player->streamer,
+ element,
+ FALSE,
+ type,
+ (guint64)dur_bytes); /* no meaning at the moment */
+ return;
+ }
+
+ /* update mq setting */
+ if (g_strrstr(factory_name, "parsebin") && (!mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst)) {
+ GstIterator *iter = NULL;
+ GValue item = {0, };
+ GstElement *ch_element = NULL;
+ GstElementFactory *ch_factory = NULL;
+
+ iter = gst_bin_iterate_recurse(child);
+ if (iter != NULL) {
+ while (gst_iterator_next(iter, &item) == GST_ITERATOR_OK) {
+ ch_element = g_value_get_object(&item);
+ ch_factory = gst_element_get_factory(ch_element);
+ LOGD("children factory %s", GST_OBJECT_NAME(ch_factory));
+ if (g_strrstr(GST_OBJECT_NAME(ch_factory), "multiqueue")) {
+ LOGD("get multiqueue");
+ player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
+ player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = ch_element;
+
+ /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h */
+ _mm_player_streaming_set_multiqueue(player->streamer, ch_element);
+ g_value_reset(&item);
+ break;
+ }
+ g_value_reset(&item);
+ }
+ gst_iterator_free(iter);
+ }
+ }
+ }
+
+ if (g_strrstr(factory_name, "parsebin")) {
+ int video_codec_type = 0;
+ int audio_codec_type = 0;
+
+ g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL);
+ g_object_set(G_OBJECT(element), "message-forward", TRUE, NULL);
+
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type);
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type);
+
+ /* CAUTION: if there is hw decoder, the rank value has to be higher than sw decoder
+ and codec default type in ini has to be hw.
+ */
+ if (video_codec_type == MM_PLAYER_CODEC_TYPE_SW)
+ g_object_set(G_OBJECT(child), "force-sw-decoder-for-video", TRUE, NULL);
+ if (audio_codec_type == MM_PLAYER_CODEC_TYPE_SW)
+ g_object_set(G_OBJECT(child), "force-sw-decoder-for-audio", 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),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type", G_CALLBACK(_mmplayer_gst_decode_unknown_type), (gpointer)player);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(element),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue", G_CALLBACK(_mmplayer_gst_decode_autoplug_continue), (gpointer)player);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(element),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select", G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(child),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "request-resource", G_CALLBACK(__mmplayer_gst_decode_request_resource), (gpointer)player);
+
+ } else {
+ _mmplayer_gst_element_added((GstElement *)child, element, data);
+ }
+ return;
+}
+
+void
+__mmplayer_gst_deep_element_removed(GstElement *bin, GstBin *child, GstElement *element, gpointer data)
+{
+ LOGD("%s > %s > %s", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(child), GST_ELEMENT_NAME(element));
+ return;
+}
+
+static GstElement *
+__mmplayer_gst_make_uridecodebin(mmplayer_t *player)
+{
+ GstElement *uridecodebin3 = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
+
+ uridecodebin3 = gst_element_factory_make("uridecodebin3", "uridecodebin3");
+ if (!uridecodebin3) {
+ LOGE("failed to create uridecodebin3");
+ return NULL;
+ }
+
+ /* get attribute */
+ 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,
+ "buffer-size", DEFAULT_BUFFER_SIZE_BYTES, NULL);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-notify::source", G_CALLBACK(__mmplayer_gst_found_source), (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);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed", G_CALLBACK(_mmplayer_gst_decode_pad_removed), (gpointer)player);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads", G_CALLBACK(_mmplayer_gst_decode_no_more_pads), (gpointer)player);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "select-stream", G_CALLBACK(__mmplayer_gst_select_stream), (gpointer)player);
+
+/* FIXME: need to be added for gapless playback
+ _mmplayer_add_signal_connection(player, G_OBJECT(element),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "about-to-finish", G_CALLBACK(_mmplayer_gst_decode_drained), (gpointer)player);
+*/
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-element-added", G_CALLBACK(__mmplayer_gst_deep_element_added), (gpointer)player);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-element-removed", G_CALLBACK(__mmplayer_gst_deep_element_removed), (gpointer)player);
+
+ if (MMPLAYER_URL_HAS_DASH_SUFFIX(player))
+ LOGW("[DASH] this is still experimental feature");
+
+ MMPLAYER_FLEAVE();
+ return uridecodebin3;
+}
+
+static GstElement *
+__mmplayer_gst_make_http_src(mmplayer_t *player)
{
- GstElement* element = NULL;
+#define MAX_RETRY_COUNT 10
+ GstElement *element = NULL;
MMHandleType attrs = 0;
gchar *user_agent, *cookies, **cookie_list;
gint http_timeout = DEFAULT_HTTP_TIMEOUT;
+
user_agent = cookies = NULL;
cookie_list = NULL;
/* setting property to streaming source */
g_object_set(G_OBJECT(element), "location", player->profile.uri,
- "timeout", http_timeout, "blocksize", (unsigned long)(64*1024), NULL);
+ "timeout", http_timeout, "blocksize", (unsigned long)(64 * 1024),
+ "retries", MAX_RETRY_COUNT, NULL);
/* parsing cookies */
- if ((cookie_list = util_get_cookie_list((const char*)cookies))) {
+ if ((cookie_list = _mmplayer_get_cookie_list((const char *)cookies))) {
g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
g_strfreev(cookie_list);
}
return element;
}
-static GstElement*
-__mmplayer_gst_create_file_src(mm_player_t* player)
+static GstElement *
+__mmplayer_gst_make_file_src(mmplayer_t *player)
{
- GstElement* element = NULL;
+ GstElement *element = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
LOGD("using filesrc for 'file://' handler");
- if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
+ if (!_mmplayer_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
LOGE("failed to get storage info");
return NULL;
}
return NULL;
}
- g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */
+ g_object_set(G_OBJECT(element), "location", (player->profile.uri) + 7, NULL); /* uri+7 -> remove "file:// */
MMPLAYER_FLEAVE();
return element;
}
-static gboolean __mmplayer_gst_msg_push(GstBus *bus, GstMessage *msg, gpointer data)
+static gboolean
+__mmplayer_gst_msg_push(GstBus *bus, GstMessage *msg, gpointer data)
{
- mm_player_t *player = (mm_player_t *) data;
+ mmplayer_t *player = (mmplayer_t *)data;
g_return_val_if_fail(player, FALSE);
g_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE);
-
gst_message_ref(msg);
g_mutex_lock(&player->bus_msg_q_lock);
static gpointer __mmplayer_gst_bus_msg_thread(gpointer data)
{
- mm_player_t *player = (mm_player_t*)(data);
+ mmplayer_t *player = (mmplayer_t *)(data);
GstMessage *msg = NULL;
- GstBus *bus = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player &&
player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
NULL);
- bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
- if (!bus) {
- LOGE("cannot get BUS from the pipeline");
- return NULL;
- }
-
MMPLAYER_BUS_MSG_THREAD_LOCK(player);
LOGD("[handle: %p] gst bus msg thread will be started.", player);
}
MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
- gst_object_unref(GST_OBJECT(bus));
-
MMPLAYER_FLEAVE();
+
return NULL;
}
-#if 0
-#endif
-
-int
-__mmplayer_gst_set_state(mm_player_t* player, GstElement * element, GstState state, gboolean async, gint timeout)
+static int
+__mmplayer_gst_check_duration(mmplayer_t *player, gint64 position)
{
- GstState element_state = GST_STATE_VOID_PENDING;
- GstState element_pending_state = GST_STATE_VOID_PENDING;
- GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
+ gint64 dur_nsec = 0;
MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(element, MM_ERROR_INVALID_ARGUMENT);
-
- LOGD("setting [%s] element state to : %s\n", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
-
- /* set state */
- ret = gst_element_set_state(element, state);
-
- if (ret == GST_STATE_CHANGE_FAILURE) {
- LOGE("failed to set [%s] state\n", GST_ELEMENT_NAME(element));
-
- /* dump state of all element */
- __mmplayer_dump_pipeline_state(player);
+ if (MMPLAYER_IS_MS_BUFF_SRC(player))
+ return MM_ERROR_NONE;
+
+ /* NOTE : duration cannot be zero except live streaming.
+ * Since some element could have some timing problemn with quering duration, try again.
+ */
+ if (player->duration == 0) {
+ if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
+ /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
+ * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
+ if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
+ (_mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
+ player->pending_seek.is_pending = true;
+ player->pending_seek.pos = position;
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
+ return MM_ERROR_PLAYER_NO_OP;
+ } else {
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ return MM_ERROR_PLAYER_SEEK;
+ }
+ }
+ player->duration = dur_nsec;
+ }
+
+ if (player->duration > 0 && player->duration < position) {
+ LOGE("invalid pos %"G_GINT64_FORMAT", dur: %"G_GINT64_FORMAT, position, player->duration);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+}
+
+static gboolean
+__mmplayer_gst_check_seekable(mmplayer_t *player)
+{
+ GstQuery *query = NULL;
+ gboolean seekable = FALSE;
+
+ if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
+ return TRUE;
+ }
+
+ query = gst_query_new_seeking(GST_FORMAT_TIME);
+ if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
+ gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);
+ gst_query_unref(query);
+
+ if (!seekable) {
+ LOGW("non-seekable content");
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ return FALSE;
+ }
+ } else {
+ LOGW("failed to get seeking query");
+ gst_query_unref(query); /* keep seeking operation */
+ }
+
+ return TRUE;
+}
+
+int
+_mmplayer_gst_set_state(mmplayer_t *player, GstElement *element, GstState state, gboolean async, gint timeout)
+{
+ GstState element_state = GST_STATE_VOID_PENDING;
+ GstState element_pending_state = GST_STATE_VOID_PENDING;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
+
+ MMPLAYER_FENTER();
+
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(element, MM_ERROR_INVALID_ARGUMENT);
+
+ LOGD("setting [%s] element state to : %s", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
+
+ /* set state */
+ ret = gst_element_set_state(element, state);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ LOGE("failed to set [%s] state", GST_ELEMENT_NAME(element));
+
+ /* dump state of all element */
+ _mmplayer_dump_pipeline_state(player);
return MM_ERROR_PLAYER_INTERNAL;
}
/* return here so state transition to be done in async mode */
if (async) {
- LOGD("async state transition. not waiting for state complete.\n");
+ LOGD("async state transition. not waiting for state complete.");
return MM_ERROR_NONE;
}
/* wait for state transition */
ret = gst_element_get_state(element, &element_state, &element_pending_state, timeout * GST_SECOND);
-
if (ret == GST_STATE_CHANGE_FAILURE || (state != element_state)) {
- LOGE("failed to change [%s] element state to [%s] within %d sec\n",
+ LOGE("failed to change [%s] element state to [%s] within %d sec",
GST_ELEMENT_NAME(element),
gst_element_state_get_name(state), timeout);
- LOGE(" [%s] state : %s pending : %s \n",
+ LOGE(" [%s] state : %s pending : %s",
GST_ELEMENT_NAME(element),
gst_element_state_get_name(element_state),
gst_element_state_get_name(element_pending_state));
/* dump state of all element */
- __mmplayer_dump_pipeline_state(player);
+ _mmplayer_dump_pipeline_state(player);
return MM_ERROR_PLAYER_INTERNAL;
}
- LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
+ LOGD("[%s] element state has changed", GST_ELEMENT_NAME(element));
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
-int __mmplayer_gst_start(mm_player_t* player)
+int
+_mmplayer_gst_start(mmplayer_t *player)
{
int ret = MM_ERROR_NONE;
gboolean async = FALSE;
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
- /* NOTE : if SetPosition was called before Start. do it now */
- /* streaming doesn't support it. so it should be always sync */
- /* !!create one more api to check if there is pending seek rather than checking variables */
+ /* NOTE : if SetPosition was called before Start. do it now
+ * streaming doesn't support it. so it should be always sync
+ * !!create one more api to check if there is pending seek rather than checking variables
+ */
if (player->pending_seek.is_pending && !MMPLAYER_IS_STREAMING(player)) {
MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
- ret = __mmplayer_gst_pause(player, FALSE);
+ ret = _mmplayer_gst_pause(player, FALSE);
if (ret != MM_ERROR_NONE) {
LOGE("failed to set state to PAUSED for pending seek");
return ret;
MMPLAYER_PRINT_STATE(player);
/* set pipeline state to PLAYING */
- ret = __mmplayer_gst_set_state(player,
+ ret = _mmplayer_gst_set_state(player,
player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
-
- if (ret == MM_ERROR_NONE) {
- MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
- } else {
+ if (ret != MM_ERROR_NONE) {
LOGE("failed to set state to PLAYING");
return ret;
}
+ MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
+
/* generating debug info before returning error */
MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-start");
return ret;
}
-int __mmplayer_gst_stop(mm_player_t* player)
+int
+_mmplayer_gst_stop(mmplayer_t *player)
{
GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
MMHandleType attrs = 0;
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
- LOGE("cannot get content attribute\n");
+ LOGE("cannot get content attribute");
return MM_ERROR_PLAYER_INTERNAL;
}
(player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked))
rewind = TRUE;
- if (player->es_player_push_mode || MMPLAYER_IS_HTTP_PD(player)) {
+ if (player->es_player_push_mode)
/* disable the async state transition because there could be no data in the pipeline */
- __mmplayer_gst_handle_async(player, FALSE, MMPLAYER_SINK_ALL);
- }
+ __mmplayer_gst_set_async(player, FALSE, MMPLAYER_SINK_ALL);
/* set gst state */
- ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout);
+ ret = _mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout);
- if (player->es_player_push_mode || MMPLAYER_IS_HTTP_PD(player)) {
+ if (player->es_player_push_mode) {
/* enable the async state transition as default operation */
- __mmplayer_gst_handle_async(player, TRUE, MMPLAYER_SINK_ALL);
+ __mmplayer_gst_set_async(player, TRUE, MMPLAYER_SINK_ALL);
}
/* return if set_state has failed */
if (ret != MM_ERROR_NONE) {
- LOGE("failed to set state.\n");
+ LOGE("failed to set state.");
return ret;
}
/* rewind */
if (rewind) {
- if (!__mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
+ if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
- LOGW("failed to rewind\n");
+ LOGW("failed to rewind");
ret = MM_ERROR_PLAYER_SEEK;
}
}
if (change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL) {
MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
} else {
- LOGE("fail to stop player.\n");
+ LOGE("fail to stop player.");
ret = MM_ERROR_PLAYER_INTERNAL;
- __mmplayer_dump_pipeline_state(player);
+ _mmplayer_dump_pipeline_state(player);
}
/* generate dot file if enabled */
return ret;
}
-int __mmplayer_gst_pause(mm_player_t* player, gboolean async)
+int
+_mmplayer_gst_pause(mmplayer_t *player, gboolean async)
{
int ret = MM_ERROR_NONE;
MMPLAYER_PRINT_STATE(player);
/* set pipeline status to PAUSED */
- ret = __mmplayer_gst_set_state(player,
+ ret = _mmplayer_gst_set_state(player,
player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
- if (FALSE == async) {
- if (ret != MM_ERROR_NONE) {
- GstMessage *msg = NULL;
- GTimer *timer = NULL;
- gdouble MAX_TIMEOUT_SEC = 3;
+ if (async)
+ goto EXIT;
- LOGE("failed to set state to PAUSED");
+ if (ret != MM_ERROR_NONE) {
+ GstMessage *msg = NULL;
+ GTimer *timer = NULL;
+ gdouble MAX_TIMEOUT_SEC = 3;
- if (!player->bus_watcher) {
- LOGE("there is no bus msg thread. pipeline is shutting down.");
- return ret;
- }
+ LOGE("failed to set state to PAUSED");
- if (player->msg_posted) {
- LOGE("error msg is already posted.");
- return ret;
- }
+ if (!player->bus_watcher) {
+ LOGE("there is no bus msg thread. pipeline is shutting down.");
+ return ret;
+ }
- timer = g_timer_new();
- g_timer_start(timer);
+ if (player->msg_posted) {
+ LOGE("error msg is already posted.");
+ return ret;
+ }
- GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
+ timer = g_timer_new();
+ g_timer_start(timer);
- do {
- msg = gst_bus_timed_pop(bus, 100 * GST_MSECOND);
- if (msg) {
- if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
- GError *error = NULL;
+ GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
- /* parse error code */
- gst_message_parse_error(msg, &error, NULL);
+ do {
+ msg = gst_bus_timed_pop(bus, 100 * GST_MSECOND);
+ if (msg) {
+ if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
+ GError *error = NULL;
- if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
- /* Note : the streaming error from the streaming source is handled
- * using __mmplayer_handle_streaming_error.
- */
- __mmplayer_handle_streaming_error(player, msg);
+ /* parse error code */
+ gst_message_parse_error(msg, &error, NULL);
- } else if (error) {
- LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
+ if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
+ /* Note : the streaming error from the streaming source is handled
+ * using __mmplayer_handle_streaming_error.
+ */
+ __mmplayer_handle_streaming_error(player, msg);
- if (error->domain == GST_STREAM_ERROR)
- ret = __mmplayer_gst_handle_stream_error(player, error, msg);
- else if (error->domain == GST_RESOURCE_ERROR)
- ret = __mmplayer_gst_handle_resource_error(player, error->code, NULL);
- else if (error->domain == GST_LIBRARY_ERROR)
- ret = __mmplayer_gst_handle_library_error(player, error->code);
- else if (error->domain == GST_CORE_ERROR)
- ret = __mmplayer_gst_handle_core_error(player, error->code);
+ } else if (error) {
+ LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
- g_error_free(error);
- }
- player->msg_posted = TRUE;
+ if (error->domain == GST_STREAM_ERROR)
+ ret = __mmplayer_gst_handle_stream_error(player, error, msg);
+ else if (error->domain == GST_RESOURCE_ERROR)
+ ret = __mmplayer_gst_handle_resource_error(player, error->code, NULL);
+ else if (error->domain == GST_LIBRARY_ERROR)
+ ret = __mmplayer_gst_handle_library_error(player, error->code);
+ else if (error->domain == GST_CORE_ERROR)
+ ret = __mmplayer_gst_handle_core_error(player, error->code);
+
+ g_error_free(error);
}
- gst_message_unref(msg);
+ player->msg_posted = TRUE;
}
- } while (!player->msg_posted && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
- /* clean */
- gst_object_unref(bus);
- g_timer_stop(timer);
- g_timer_destroy(timer);
-
- return ret;
+ gst_message_unref(msg);
+ }
+ } while (!player->msg_posted && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
+ /* clean */
+ gst_object_unref(bus);
+ g_timer_stop(timer);
+ g_timer_destroy(timer);
- } else if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_stream_cb) &&
- (!player->pipeline->videobin) && (!player->pipeline->audiobin)) {
+ return ret;
+ }
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_decoded_cb) &&
+ (!player->pipeline->videobin) && (!player->pipeline->audiobin))
return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
-
- } else {
- MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
- }
}
+ MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
+
+EXIT:
/* generate dot file before returning error */
MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-pause");
return ret;
}
-int __mmplayer_gst_resume(mm_player_t* player, gboolean async)
+int
+_mmplayer_gst_resume(mmplayer_t *player, gboolean async)
{
int ret = MM_ERROR_NONE;
gint timeout = 0;
/* set pipeline state to PLAYING */
timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
- ret = __mmplayer_gst_set_state(player,
+ ret = _mmplayer_gst_set_state(player,
player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout);
if (ret != MM_ERROR_NONE) {
LOGE("failed to set state to PLAYING");
goto EXIT;
- } else {
- if (async == FALSE)
- MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
}
+ if (!async)
+ MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
+
EXIT:
/* generate dot file */
MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
/* sending event to one of sinkelements */
gboolean
-__mmplayer_gst_send_event_to_sink(mm_player_t* player, GstEvent* event)
+_mmplayer_gst_send_event_to_sink(mmplayer_t *player, GstEvent *event)
{
- GstEvent * event2 = NULL;
+ GstEvent *event2 = NULL;
GList *sinks = NULL;
gboolean res = FALSE;
MMPLAYER_FENTER();
gst_event_ref(event);
if ((res = gst_element_send_event(sink, event))) {
- LOGD("sending event[%s] to sink element [%s] success!\n",
+ LOGD("sending event[%s] to sink element [%s] success!",
GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
/* rtsp case, asyn_done is not called after seek during pause state */
if (MMPLAYER_IS_RTSP_STREAMING(player)) {
if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
- LOGD("RTSP seek completed, after pause state..\n");
+ LOGD("RTSP seek completed, after pause state..");
player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
}
}
}
- LOGD("sending event[%s] to sink element [%s] failed. try with next one.\n",
+ LOGD("sending event[%s] to sink element [%s] failed. try with next one.",
GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
}
/* Note : Textbin is not linked to the video or audio bin.
* It needs to send the event to the text sink seperatelly.
*/
- if (player->play_subtitle && player->pipeline) {
+ if (player->play_subtitle && player->pipeline) {
GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
if (GST_IS_ELEMENT(text_sink)) {
gst_event_ref(event2);
if ((res = gst_element_send_event(text_sink, event2)))
- LOGD("sending event[%s] to subtitle sink element [%s] success!\n",
- GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
+ LOGD("sending event[%s] to subtitle sink element [%s] success!",
+ GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
else
- LOGE("sending event[%s] to subtitle sink element [%s] failed!\n",
- GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
+ LOGE("sending event[%s] to subtitle sink element [%s] failed!",
+ GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
gst_event_unref(event2);
}
- }
+ }
gst_event_unref(event);
}
gboolean
-__mmplayer_gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
+_mmplayer_gst_seek(mmplayer_t *player, GstElement *element, gdouble rate,
GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
gint64 cur, GstSeekType stop_type, gint64 stop)
{
- GstEvent* event = NULL;
+ GstEvent *event = NULL;
gboolean result = FALSE;
MMPLAYER_FENTER();
event = gst_event_new_seek(rate, format, flags, cur_type,
cur, stop_type, stop);
- result = __mmplayer_gst_send_event_to_sink(player, event);
+ result = _mmplayer_gst_send_event_to_sink(player, event);
MMPLAYER_FLEAVE();
}
int
-__mmplayer_gst_set_position(mm_player_t* player, int format, gint64 position, gboolean internal_called)
+_mmplayer_gst_set_position(mmplayer_t *player, gint64 position, gboolean internal_called)
{
- gint64 dur_nsec = 0;
+ int ret = MM_ERROR_NONE;
gint64 pos_nsec = 0;
- gboolean ret = TRUE;
gboolean accurated = FALSE;
GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
MMPLAYER_RETURN_VAL_IF_FAIL(!MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP);
- if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
- && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
+ if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING)
+ && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
goto PENDING;
- if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
- /* check duration */
- /* NOTE : duration cannot be zero except live streaming.
- * Since some element could have some timing problemn with quering duration, try again.
- */
- if (player->duration == 0) {
- if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
- /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
- * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
- player->pending_seek.is_pending = TRUE;
- player->pending_seek.format = format;
- player->pending_seek.pos = position;
- player->seek_state = MMPLAYER_SEEK_NONE;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
- return MM_ERROR_NONE;
- } else {
- goto SEEK_ERROR;
- }
- }
- player->duration = dur_nsec;
- }
+ ret = __mmplayer_gst_check_duration(player, position);
+ if (ret != MM_ERROR_NONE) {
+ LOGE("failed to check duration 0x%X", ret);
+ return (ret == MM_ERROR_PLAYER_NO_OP) ? MM_ERROR_NONE : ret;
}
- LOGD("playback rate: %f\n", player->playback_rate);
-
- mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
- if (accurated)
- seek_flags |= GST_SEEK_FLAG_ACCURATE;
- else
- seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
-
- /* do seek */
- switch (format) {
- case MM_PLAYER_POS_FORMAT_TIME:
- {
- if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
- GstQuery *query = NULL;
- gboolean seekable = FALSE;
-
- /* check position is valid or not */
- if (position > player->duration)
- goto INVALID_ARGS;
- query = gst_query_new_seeking(GST_FORMAT_TIME);
- if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
- gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);
- gst_query_unref(query);
-
- if (!seekable) {
- LOGW("non-seekable content");
- player->seek_state = MMPLAYER_SEEK_NONE;
- return MM_ERROR_PLAYER_NO_OP;
- }
- } else {
- LOGW("failed to get seeking query");
- gst_query_unref(query); /* keep seeking operation */
- }
-
- LOGD("seeking to(%"G_GINT64_FORMAT") nsec, duration is %"G_GINT64_FORMAT" nsec\n", position, player->duration);
-
- /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
- But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
- This causes problem is position calculation during normal pause resume scenarios also.
- Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
- (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
- if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
- LOGW("getting current position failed in seek\n");
-
- player->last_position = pos_nsec;
- g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
- }
-
- if (player->seek_state != MMPLAYER_SEEK_NONE) {
- LOGD("not completed seek");
- return MM_ERROR_PLAYER_DOING_SEEK;
- }
- }
-
- if (!internal_called)
- player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
-
- if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked)) {
- gint64 cur_time = 0;
-
- /* get current position */
- gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
-
- /* flush */
- GstEvent *event = gst_event_new_seek(1.0,
- GST_FORMAT_TIME,
- (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
- GST_SEEK_TYPE_SET, cur_time,
- GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
- if (event)
- __mmplayer_gst_send_event_to_sink(player, event);
-
- if (!MMPLAYER_IS_RTSP_STREAMING(player))
- __mmplayer_gst_pause(player, FALSE);
- }
+ if (!__mmplayer_gst_check_seekable(player))
+ return MM_ERROR_PLAYER_NO_OP;
- pos_nsec = position;
+ LOGD("seeking to(%"G_GINT64_FORMAT") nsec, rate: %f, dur: %"G_GINT64_FORMAT" nsec",
+ position, player->playback_rate, player->duration);
- /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
- that's why set position through property. */
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
- (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
- (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
- (!player->videodec_linked) && (!player->audiodec_linked)) {
+ /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
+ But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
+ This causes problem is position calculation during normal pause resume scenarios also.
+ Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
+ if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
+ (_mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
+ if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
+ LOGW("getting current position failed in seek");
- g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", pos_nsec, NULL);
- LOGD("[%s] set position =%"GST_TIME_FORMAT,
- GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(pos_nsec));
- player->seek_state = MMPLAYER_SEEK_NONE;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
- } else {
- ret = __mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
- GST_FORMAT_TIME, seek_flags,
- GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
- }
+ player->last_position = pos_nsec;
+ g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
+ }
- if (!ret) {
- LOGE("failed to set position.");
- goto SEEK_ERROR;
- }
+ if (player->seek_state != MMPLAYER_SEEK_NONE) {
+ LOGD("not completed seek");
+ return MM_ERROR_PLAYER_DOING_SEEK;
}
- break;
- case MM_PLAYER_POS_FORMAT_PERCENT:
- {
- LOGD("seeking to %"G_GINT64_FORMAT"%%", position);
+ if (!internal_called)
+ player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
- if (player->seek_state != MMPLAYER_SEEK_NONE) {
- LOGD("not completed seek");
- return MM_ERROR_PLAYER_DOING_SEEK;
- }
+ /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
+ that's why set position through property. */
+ if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
+ (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
+ (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
+ (!player->videodec_linked) && (!player->audiodec_linked)) {
- if (!internal_called)
- player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
+ LOGD("[%s] set position =%"GST_TIME_FORMAT,
+ GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(position));
- /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
- pos_nsec = (gint64)((position * player->duration) / 100);
- ret = __mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
+ g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", position, NULL);
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
+ } else {
+ mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
+ if (accurated)
+ seek_flags |= GST_SEEK_FLAG_ACCURATE;
+ else
+ seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
+
+ if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
GST_FORMAT_TIME, seek_flags,
- GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
- if (!ret) {
- LOGE("failed to set position. pos[%"G_GINT64_FORMAT"] dur[%"G_GINT64_FORMAT"] ", pos_nsec, player->duration);
+ GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
+ LOGE("failed to set position");
goto SEEK_ERROR;
}
}
- break;
-
- default:
- goto INVALID_ARGS;
- }
/* NOTE : store last seeking point to overcome some bad operation
- * (returning zero when getting current position) of some elements
- */
- player->last_position = pos_nsec;
+ * (returning zero when getting current position) of some elements
+ */
+ player->last_position = position;
/* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
if (player->playback_rate > 1.0)
_mmplayer_set_playspeed((MMHandleType)player, player->playback_rate, FALSE);
- if ((!internal_called) &&
- (player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
+ if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
LOGD("buffering should be reset after seeking");
player->streamer->buffering_state = MM_PLAYER_BUFFERING_ABORT;
player->streamer->buffering_percent = 100; /* after seeking, new per can be non-zero. */
return MM_ERROR_NONE;
PENDING:
- player->pending_seek.is_pending = TRUE;
- player->pending_seek.format = format;
+ player->pending_seek.is_pending = true;
player->pending_seek.pos = position;
- LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%"G_GINT64_FORMAT").\n",
+ LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%"G_GINT64_FORMAT")",
MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)),
MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)),
player->pending_seek.pos);
return MM_ERROR_NONE;
-INVALID_ARGS:
- LOGE("invalid arguments, position: %"G_GINT64_FORMAT" dur : %"G_GINT64_FORMAT" format : %d \n", position, player->duration, format);
- return MM_ERROR_INVALID_ARGUMENT;
-
SEEK_ERROR:
player->seek_state = MMPLAYER_SEEK_NONE;
return MM_ERROR_PLAYER_SEEK;
}
int
-__mmplayer_gst_get_position(mm_player_t* player, int format, gint64* position)
+_mmplayer_gst_get_position(mmplayer_t *player, gint64 *position)
{
#define TRICKPLAY_OFFSET GST_MSECOND
- MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
+ mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
gint64 pos_nsec = 0;
gboolean ret = TRUE;
player->last_position = pos_nsec;
}
- switch (format) {
- case MM_PLAYER_POS_FORMAT_TIME:
- *position = pos_nsec;
- break;
-
- case MM_PLAYER_POS_FORMAT_PERCENT:
- {
- if (player->duration <= 0) {
- LOGD("duration is [%"G_GINT64_FORMAT"], so returning position 0\n", player->duration);
- *position = 0;
- } else {
- LOGD("position is [%"G_GINT64_FORMAT"] nsec , duration is [%"G_GINT64_FORMAT"] nsec", pos_nsec, player->duration);
- *position = (gint64)(pos_nsec * 100 / player->duration);
- }
- break;
- }
- default:
- return MM_ERROR_PLAYER_INTERNAL;
- }
+ *position = pos_nsec;
return MM_ERROR_NONE;
}
-int __mmplayer_gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
+int
+_mmplayer_gst_get_buffer_position(mmplayer_t *player, int *start_pos, int *end_pos)
{
#define STREAMING_IS_FINISHED 0
#define BUFFERING_MAX_PER 100
#define DEFAULT_PER_VALUE -1
#define CHECK_PERCENT_VALUE(a, min, max)(((a) > (min)) ? (((a) < (max)) ? (a) : (max)) : (min))
- MMPlayerGstElement *mainbin = NULL;
- gint start_per = DEFAULT_PER_VALUE, stop_per = DEFAULT_PER_VALUE;
+ mmplayer_gst_element_t *mainbin = NULL;
+ gint start_per = DEFAULT_PER_VALUE, end_per = DEFAULT_PER_VALUE;
gint64 buffered_total = 0;
gint64 position = 0;
gint buffered_sec = -1;
player->pipeline->mainbin,
MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT);
+ MMPLAYER_RETURN_VAL_IF_FAIL(start_pos && end_pos, MM_ERROR_INVALID_ARGUMENT);
*start_pos = 0;
- *stop_pos = 0;
+ *end_pos = 0;
if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
/* and rtsp is not ready yet. */
- LOGW("it's only used for http streaming case.\n");
+ LOGW("it's only used for http streaming case");
return MM_ERROR_PLAYER_NO_OP;
}
- if (format != MM_PLAYER_POS_FORMAT_PERCENT) {
- LOGW("Time format is not supported yet.\n");
- return MM_ERROR_INVALID_ARGUMENT;
- }
-
if (content_size_time <= 0 || content_size_bytes <= 0) {
- LOGW("there is no content size.");
+ LOGW("there is no content size");
return MM_ERROR_NONE;
}
- if (__mmplayer_gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position) != MM_ERROR_NONE) {
- LOGW("fail to get current position.");
+ if (_mmplayer_gst_get_position(player, &position) != MM_ERROR_NONE) {
+ LOGW("fail to get current position");
return MM_ERROR_NONE;
}
GST_TIME_AS_MSECONDS(position), (guint)GST_TIME_AS_SECONDS(content_size_time), content_size_bytes);
mainbin = player->pipeline->mainbin;
- start_per = (gint)(floor(100 *(gdouble)position / (gdouble)content_size_time));
+ start_per = (gint)(floor(100 * (gdouble)position / (gdouble)content_size_time));
if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
GstQuery *query = NULL;
if (gst_element_query_position(mainbin[MMPLAYER_M_SRC].gst,
GST_FORMAT_BYTES, &buffered_total)) {
LOGD("buffered_total %"G_GINT64_FORMAT, buffered_total);
- stop_per = 100 * buffered_total / content_size_bytes;
+ end_per = 100 * buffered_total / content_size_bytes;
}
} else {
/* GST_BUFFERING_TIMESHIFT or GST_BUFFERING_DOWNLOAD */
buffered_total += (stop_byte - start_byte);
}
- } else
- stop_per = BUFFERING_MAX_PER;
+ } else {
+ end_per = BUFFERING_MAX_PER;
+ }
}
gst_query_unref(query);
}
- if (stop_per == DEFAULT_PER_VALUE) {
+ if (end_per == DEFAULT_PER_VALUE) {
guint dur_sec = (guint)(content_size_time/GST_SECOND);
if (dur_sec > 0) {
- guint avg_byterate = (guint)(content_size_bytes/dur_sec);
+ guint avg_byterate = (guint)(content_size_bytes / dur_sec);
/* buffered size info from multiqueue */
if (mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) {
}
if (avg_byterate > 0)
- buffered_sec = (gint)(ceil((gdouble)buffered_total/(gdouble)avg_byterate));
+ buffered_sec = (gint)(ceil((gdouble)buffered_total / (gdouble)avg_byterate));
else if (player->total_maximum_bitrate > 0)
- buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_maximum_bitrate));
+ buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total) / (gdouble)player->total_maximum_bitrate));
else if (player->total_bitrate > 0)
- buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_bitrate));
+ buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total) / (gdouble)player->total_bitrate));
if (buffered_sec >= 0)
- stop_per = start_per +(gint)(ceil)(100*(gdouble)buffered_sec/(gdouble)dur_sec);
+ end_per = start_per + (gint)(ceil)(100 * (gdouble)buffered_sec / (gdouble)dur_sec);
}
}
*start_pos = CHECK_PERCENT_VALUE(start_per, 0, 100);
- *stop_pos = CHECK_PERCENT_VALUE(stop_per, *start_pos, 100);
+ *end_pos = CHECK_PERCENT_VALUE(end_per, *start_pos, 100);
- LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %lu~%lu\n",
- buffered_total, buffered_sec, *start_pos, *stop_pos);
+ LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %d~%d",
+ buffered_total, buffered_sec, *start_pos, *end_pos);
return MM_ERROR_NONE;
}
-int __mmplayer_gst_build_es_pipeline(mm_player_t* player)
+GstElement *
+_mmplayer_gst_create_source(mmplayer_t *player)
{
- MMHandleType attrs = 0;
+ GstElement *element = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
- player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ player->pipeline->mainbin, NULL);
- /* get profile attribute */
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("failed to get content attribute");
- return MM_ERROR_PLAYER_INTERNAL;
+ /* setup source for gapless play */
+ switch (player->profile.uri_type) {
+ /* file source */
+ case MM_PLAYER_URI_TYPE_FILE:
+ element = __mmplayer_gst_make_file_src(player);
+ break;
+ case MM_PLAYER_URI_TYPE_URL_HTTP:
+ element = __mmplayer_gst_make_http_src(player);
+ break;
+ default:
+ LOGE("not support uri type %d", player->profile.uri_type);
+ break;
+ }
+
+ if (!element) {
+ LOGE("failed to create source element");
+ return NULL;
}
+ MMPLAYER_FLEAVE();
+ return element;
+}
+
+int
+_mmplayer_gst_build_es_pipeline(mmplayer_t *player)
+{
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
SECURE_LOGD("uri : %s", player->profile.uri);
- mm_attrs_set_int_by_name(attrs, "profile_prepare_async", TRUE);
- if (mmf_attrs_commit(attrs)) /* return -1 if error */
- LOGE("failed to commit");
+ mm_player_set_attribute((MMHandleType)player, NULL, "profile_prepare_async", TRUE, NULL);
- if (player->v_stream_caps && !__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_VIDEO, player->v_stream_caps))
+ if ((player->v_stream_caps) &&
+ !(__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_VIDEO, player->v_stream_caps)))
return MM_ERROR_PLAYER_INTERNAL;
- if (player->a_stream_caps && !__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_AUDIO, player->a_stream_caps))
+ if ((player->a_stream_caps) &&
+ !(__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_AUDIO, player->a_stream_caps)))
return MM_ERROR_PLAYER_INTERNAL;
- if (player->s_stream_caps && !__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_TEXT, player->s_stream_caps))
+ if ((player->s_stream_caps) &&
+ !(__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_TEXT, player->s_stream_caps)))
return MM_ERROR_PLAYER_INTERNAL;
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
-int __mmplayer_gst_build_pd_pipeline(mm_player_t* player)
+int
+_mmplayer_gst_build_pipeline_with_src(mmplayer_t *player)
{
- MMPlayerGstElement *mainbin = NULL;
- GstElement *pd_src = NULL;
- GstElement *pd_queue = NULL;
- GstElement *pd_decodebin = NULL;
- GList* element_bucket = NULL;
- MMHandleType attrs = 0;
- gchar *path = NULL;
- gint pre_buffering_time = player->streamer->buffering_req.prebuffer_time;
+ 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);
- /* get profile attribute */
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("failed to get content attribute");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- LOGD("http playback with progressive download : %d", player->pd_mode);
-
- if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
- mm_attrs_get_string_by_name(attrs, "pd_location", &path);
- MMPLAYER_FREEIF(player->pd_file_save_path);
-
- SECURE_LOGD("PD Location : %s", path);
- if (!path) {
- LOGE("filed to find pd location");
- return MM_ERROR_PLAYER_INTERNAL;
- }
+ mainbin = player->pipeline->mainbin;
- if (!util_get_storage_info(path, &player->storage_info[MMPLAYER_PATH_VOD])) {
- LOGE("failed to get storage info");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- player->pd_file_save_path = g_strdup(path);
- }
+ LOGD("uri type %d", player->profile.uri_type);
- pd_src = gst_element_factory_make("pdpushsrc", "PD pushsrc");
- if (!pd_src) {
- LOGE("failed to create PD push source");
+ if ((player->profile.uri_type == MM_PLAYER_URI_TYPE_FILE) &&
+ (!_mmplayer_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD]))) {
return MM_ERROR_PLAYER_INTERNAL;
}
- if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
- g_object_set(G_OBJECT(pd_src), "location", player->pd_file_save_path, NULL);
- else
- g_object_set(G_OBJECT(pd_src), "location", player->profile.uri, NULL);
-
- mainbin = player->pipeline->mainbin;
-
- /* take source element */
- mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
- mainbin[MMPLAYER_M_SRC].gst = pd_src;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
+ if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) {
+ g_strlcpy(player->profile.uri, "appsrc://", MM_MAX_URL_LEN);
+ }
- /* setting queue */
- LOGD("Picked queue2 element(pre buffer : %d ms)", pre_buffering_time);
- pd_queue = gst_element_factory_make("queue2", "queue2");
- if (!pd_queue) {
- LOGE("failed to create pd buffer element");
+ autoplug_elem = __mmplayer_gst_make_uridecodebin(player);
+ if (!autoplug_elem) {
+ LOGE("failed to create uridecodebin3 element");
goto ERROR;
}
- /* take queue2 */
- mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
- mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = pd_queue;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
-
- pre_buffering_time = (pre_buffering_time > 0) ? (pre_buffering_time) : (player->ini.http_buffering_time);
-
- player->streamer->is_pd_mode = TRUE;
-
- __mm_player_streaming_set_queue2(player->streamer, pd_queue, TRUE,
- player->ini.http_max_size_bytes, pre_buffering_time, 1.0,
- player->ini.http_buffering_limit, MUXED_BUFFER_TYPE_MEM_QUEUE, NULL, 0);
+ 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;
- pd_decodebin = __mmplayer_create_decodebin(player);
- if (!pd_decodebin) {
- LOGE("failed to create decodebin");
+ if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), autoplug_elem)) {
+ LOGE("failed to add uridecodebin to pipeline");
goto ERROR;
}
- /* default size of mq in decodebin is 2M
- * but it can cause blocking issue during seeking depends on content. */
- g_object_set(G_OBJECT(pd_decodebin), "max-size-bytes", (5*1024*1024), NULL);
+ /* 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");
- mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
- mainbin[MMPLAYER_M_AUTOPLUG].gst = pd_decodebin;
-
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_AUTOPLUG]);
-
- /* add elements to pipeline */
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
- LOGE("failed to add elements to pipeline");
+ 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);
- /* linking elements in the bucket by added order. */
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
- LOGE("failed to link some elements");
+ /* 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;
}
- g_list_free(element_bucket);
-
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
ERROR:
- MMPLAYER_FREEIF(player->pd_file_save_path);
- g_list_free(element_bucket);
-
- if (mainbin[MMPLAYER_M_SRC].gst)
- gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC].gst));
-
- if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)
- gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst));
if (mainbin[MMPLAYER_M_AUTOPLUG].gst)
gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_AUTOPLUG].gst));
- mainbin[MMPLAYER_M_SRC].gst = NULL;
- mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = NULL;
+ 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(mm_player_t* player)
+int
+_mmplayer_gst_build_pipeline(mmplayer_t *player)
{
- MMPlayerGstElement *mainbin = NULL;
- GstElement* src_elem = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
+ GstElement *src_elem = NULL;
GstElement *autoplug_elem = NULL;
- GList* element_bucket = NULL;
- MMHandleType attrs = 0;
- enum MainElementID autoplug_elem_id = MMPLAYER_M_NUM;
+ GList *element_bucket = NULL;
+ main_element_id_e autoplug_elem_id = MMPLAYER_M_NUM;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
- /* get profile attribute */
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("failed to get content attribute");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
LOGD("uri type %d", player->profile.uri_type);
/* create source element */
switch (player->profile.uri_type) {
case MM_PLAYER_URI_TYPE_URL_RTSP:
- src_elem = __mmplayer_gst_create_rtsp_src(player);
+ src_elem = __mmplayer_gst_make_rtsp_src(player);
break;
case MM_PLAYER_URI_TYPE_URL_HTTP:
- src_elem = __mmplayer_gst_create_http_src(player);
+ src_elem = __mmplayer_gst_make_http_src(player);
break;
case MM_PLAYER_URI_TYPE_FILE:
- src_elem = __mmplayer_gst_create_file_src(player);
+ src_elem = __mmplayer_gst_make_file_src(player);
break;
case MM_PLAYER_URI_TYPE_SS:
{
break;
case MM_PLAYER_URI_TYPE_MEM:
{
- guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
+ GstAppStreamType stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
src_elem = gst_element_factory_make("appsrc", "mem-source");
if (!src_elem) {
}
g_object_set(src_elem, "stream-type", stream_type,
- "size", player->profile.input_mem.len, "blocksize", (guint64)20480, NULL);
+ "size", (gint64)player->profile.input_mem.len, "blocksize", 20480, NULL);
- __mmplayer_add_signal_connection(player, G_OBJECT(src_elem), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
+ _mmplayer_add_signal_connection(player, G_OBJECT(src_elem), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
G_CALLBACK(__mmplayer_gst_appsrc_seek_data_mem), (gpointer)&player->profile.input_mem);
- __mmplayer_add_signal_connection(player, G_OBJECT(src_elem), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
+ _mmplayer_add_signal_connection(player, G_OBJECT(src_elem), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
G_CALLBACK(__mmplayer_gst_appsrc_feed_data_mem), (gpointer)&player->profile.input_mem);
}
break;
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);
+ _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_create_decodebin(player);
+ autoplug_elem = _mmplayer_gst_make_decodebin(player);
if (!autoplug_elem) {
LOGE("failed to create decodebin");
goto ERROR;
/* default size of mq in decodebin is 2M
* but it can cause blocking issue during seeking depends on content. */
- g_object_set(G_OBJECT(autoplug_elem), "max-size-bytes", (5*1024*1024), NULL);
+ g_object_set(G_OBJECT(autoplug_elem), "max-size-bytes", (5 * 1024 * 1024), NULL);
}
if (autoplug_elem) {
}
/* add elements to pipeline */
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
+ if (!_mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
LOGE("failed to add elements to pipeline");
goto ERROR;
}
/* linking elements in the bucket by added order. */
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
+ if (_mmplayer_gst_element_link_bucket(element_bucket) == -1) {
LOGE("failed to link some elements");
goto ERROR;
}
/* FIXME: need to check whether this is required or not. */
- if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_RTSP_STREAMING(player)) {
+ if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_RTSP_STREAMING(player) ||
+ (player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_DEINTERLEAVE)) {
/* 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");
return MM_ERROR_PLAYER_INTERNAL;
}
-int __mmplayer_gst_add_bus_watch(mm_player_t* player)
+int
+_mmplayer_gst_add_bus_watch(mmplayer_t *player)
{
GstBus *bus = NULL;
- MMPlayerGstElement *mainbin = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
return MM_ERROR_PLAYER_INTERNAL;
}
- player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_msg_push, player);
+ player->bus_watcher = gst_bus_add_watch_full(bus, G_PRIORITY_DEFAULT,
+ (GstBusFunc)__mmplayer_gst_msg_push, player,
+ (GDestroyNotify)_mmplayer_watcher_removed_notify);
+ if (player->bus_watcher == 0) {
+ LOGE("failed to add bus watch");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ g_mutex_init(&player->bus_watcher_mutex);
+ g_cond_init(&player->bus_watcher_cond);
+
player->context.thread_default = g_main_context_get_thread_default();
if (player->context.thread_default == NULL) {
player->context.thread_default = g_main_context_default();
return MM_ERROR_NONE;
}
-GstElement* __mmplayer_gst_build_source(mm_player_t* player)
+void
+_mmplayer_activate_next_source(mmplayer_t *player, GstState target)
{
- GstElement* element = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
+ MMMessageParamType msg_param = {0,};
+ GstElement *element = NULL;
+ MMHandleType attrs = 0;
+ char *uri = NULL;
+ main_element_id_e elem_idx = MMPLAYER_M_NUM;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
- player->pipeline->mainbin, NULL);
- /* setup source for gapless play */
- switch (player->profile.uri_type) {
- /* file source */
- case MM_PLAYER_URI_TYPE_FILE:
- element = __mmplayer_gst_create_file_src(player);
- break;
- case MM_PLAYER_URI_TYPE_URL_HTTP:
- element = __mmplayer_gst_create_http_src(player);
- break;
- default:
- LOGE("not support uri type %d", player->profile.uri_type);
- break;
+ if (!player || !player->pipeline || !player->pipeline->mainbin) {
+ LOGE("player is not initialized");
+ goto ERROR;
}
+ mainbin = player->pipeline->mainbin;
+ msg_param.code = MM_ERROR_PLAYER_INTERNAL;
+
+ attrs = MMPLAYER_GET_ATTRS(player);
+ if (!attrs) {
+ LOGE("fail to get attributes");
+ goto ERROR;
+ }
+
+ mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
+
+ if (_mmplayer_parse_profile((const char *)uri, NULL, &player->profile) != MM_ERROR_NONE) {
+ LOGE("failed to parse profile");
+ msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
+ goto ERROR;
+ }
+
+ if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
+ (MMPLAYER_URL_HAS_HLS_SUFFIX(player))) {
+ LOGE("dash or hls is not supportable");
+ msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
+ goto ERROR;
+ }
+
+ element = _mmplayer_gst_create_source(player);
if (!element) {
- LOGE("failed to create source element");
- return NULL;
+ LOGE("no source element was created");
+ goto ERROR;
}
+ if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
+ LOGE("failed to add source element to pipeline");
+ gst_object_unref(GST_OBJECT(element));
+ element = NULL;
+ goto ERROR;
+ }
+
+ /* take source element */
+ mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
+ mainbin[MMPLAYER_M_SRC].gst = element;
+
+ element = NULL;
+
+ if (MMPLAYER_IS_HTTP_STREAMING(player)) {
+ if (player->streamer == NULL) {
+ player->streamer = _mm_player_streaming_create();
+ _mm_player_streaming_initialize(player->streamer, TRUE);
+ }
+
+ elem_idx = MMPLAYER_M_TYPEFIND;
+ element = gst_element_factory_make("typefind", "typefinder");
+ _mmplayer_add_signal_connection(player, G_OBJECT(element),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type", G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
+ } else {
+ elem_idx = MMPLAYER_M_AUTOPLUG;
+ element = _mmplayer_gst_make_decodebin(player);
+ }
+
+ /* check autoplug element is OK */
+ if (!element) {
+ LOGE("can not create element(%d)", elem_idx);
+ goto ERROR;
+ }
+
+ if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
+ LOGE("failed to add sinkbin to pipeline");
+ gst_object_unref(GST_OBJECT(element));
+ element = NULL;
+ goto ERROR;
+ }
+
+ mainbin[elem_idx].id = elem_idx;
+ mainbin[elem_idx].gst = element;
+
+ if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elem_idx].gst) == FALSE) {
+ LOGE("Failed to link src - autoplug(or typefind)");
+ goto ERROR;
+ }
+
+ 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_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("Failed to change state of decodebin");
+ goto ERROR;
+ }
+ }
+
+ if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("Failed to change state of src element");
+ goto ERROR;
+ }
+
+ player->gapless.stream_changed = TRUE;
+ player->gapless.running = TRUE;
MMPLAYER_FLEAVE();
- return element;
+ return;
+
+ERROR:
+ if (player) {
+ _mmplayer_set_reconfigure_state(player, FALSE);
+ if (!player->msg_posted) {
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
+ player->msg_posted = TRUE;
+ }
+ }
+ return;
}