========================================================================================== */
#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;
MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
MMPLAYER_RETURN_VAL_IF_FAIL(error, FALSE);
- /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
+ /* NOTE : do something necessary inside of __gst_handle_XXX_error. not here */
memset(&msg_param, 0, sizeof(MMMessageParamType));
} 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 translated 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. */
+/* if retval is FALSE, it will be dropped for performance. */
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_set_reconfigure_state(player, FALSE);
+ _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, &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, 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);
-
- ret = __mmplayer_gst_set_position(player, player->pending_seek.pos, FALSE);
+ LOGD("trying to play from(%"G_GINT64_FORMAT") pending position", player->pending_seek.pos);
- if (MM_ERROR_NONE != ret)
- LOGE("failed to seek pending postion. just keep staying current position.\n");
+ ret = _mmplayer_gst_set_position(player, player->pending_seek.pos, FALSE);
+ if (ret != MM_ERROR_NONE)
+ LOGE("failed to seek pending position. just keep staying current position.");
- player->pending_seek.is_pending = FALSE;
+ player->pending_seek.is_pending = false;
MMPLAYER_FLEAVE();
}
static void
-__mmplayer_gst_set_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_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_set_async(player, TRUE, MMPLAYER_TEXT_SINK);
}
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;
MMPLAYER_FENTER();
- /* NOTE : EOS event is comming multiple time. watch out it */
+ /* NOTE : EOS event is coming multiple time. watch out it */
/* check state. we only process EOS when pipeline state goes to PLAYING */
if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)) {
LOGD("EOS received on non-playing state. ignoring it");
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
+ /* translate gst error code to msl error code. then post it
* to application if needed
*/
__mmplayer_handle_gst_error(player, msg, error);
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);
player->seek_state = MMPLAYER_SEEK_NONE;
MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
} else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
- /* Considering the async state trasition in case of RTSP.
- After getting state change gst msg, seek cmpleted msg will be posted. */
+ /* Considering the async state transition in case of RTSP.
+ After getting state change gst msg, seek completed msg will be posted. */
player->seek_state = MMPLAYER_SEEK_COMPLETED;
}
}
}
} 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.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.");
+ LOGE("failed to seek pending position. 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 (MMPLAYER_IS_STREAMING(player)) {
// managed prepare async case when buffering is completed
- // pending state should be reset otherwise, it's still playing even though it's resumed after bufferging.
+ // pending state should be reset otherwise, it's still playing even though it's resumed after buffering.
if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
(MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
}
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")) {
}
/* custom message for RTSP attribute :
- RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state chaged.
+ RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state changed.
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:
- /* NOTE:Don't call gst_callback directly
+ 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.
*/
default:
__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);
- 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);
+ 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_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;
NEW_ELEMENT:
- /* excute new_element if created*/
+ /* execute 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;
}
gst_object_unref(sinkpad);
sinkpad = NULL;
- /* run. setting PLAYING here since streamming source is live source */
+ /* run. setting PLAYING here since streaming source is live source */
MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
}
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 happened 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 directly 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);
+ if (player->type_caps &&
+ !MMPLAYER_IS_HTTP_LIVE_STREAMING(player) &&
+ !MMPLAYER_IS_DASH_STREAMING(player))
+ g_object_set(G_OBJECT(element), "sink-caps", player->type_caps, 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.
+ */
+ LOGD("set codec type v(%d) a(%d)", video_codec_type, audio_codec_type);
+ if (video_codec_type == MM_PLAYER_CODEC_TYPE_SW)
+ g_object_set(G_OBJECT(child), "force-sw-decoders-for-video", TRUE, NULL);
+ if (audio_codec_type == MM_PLAYER_CODEC_TYPE_SW)
+ g_object_set(G_OBJECT(child), "force-sw-decoders-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);
+
+ _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "about-to-finish", G_CALLBACK(_mmplayer_gst_about_to_finish), (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;
return NULL;
}
- LOGD("using http streamming source [%s]", player->ini.httpsrc_element);
+ LOGD("using http streaming source [%s]", player->ini.httpsrc_element);
element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
if (!element) {
/* 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;
}
static int
-__mmplayer_gst_check_duration(mm_player_t* player, gint64 position)
+__mmplayer_gst_check_duration(mmplayer_t *player, gint64 position)
{
gint64 dur_nsec = 0;
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.
+ * Since some element could have some timing problem with querying 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;
+ (_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);
}
static gboolean
-__mmplayer_gst_check_seekable(mm_player_t* player)
+__mmplayer_gst_check_seekable(mmplayer_t *player)
{
GstQuery *query = NULL;
gboolean seekable = FALSE;
return TRUE;
}
-
-#if 0
-#endif
-
int
-__mmplayer_gst_set_state(mm_player_t* player, GstElement * element, GstState state, gboolean async, gint timeout)
+_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;
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));
+ 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\n", GST_ELEMENT_NAME(element));
+ LOGE("failed to set [%s] state", GST_ELEMENT_NAME(element));
/* dump state of all element */
- __mmplayer_dump_pipeline_state(player);
+ _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_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
if (__mmplayer_gst_pending_seek(player) != MM_ERROR_NONE)
- LOGW("failed to seek pending postion. starting from the begin of content");
+ LOGW("failed to seek pending position. starting from the begin of content");
}
LOGD("current state before doing transition");
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;
}
- /* Just set state to PAUESED and the rewind. it's usual player behavior. */
+ /* Just set state to PAUSED and the rewind. it's usual player behavior. */
timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
if ((!MMPLAYER_IS_STREAMING(player) && !MMPLAYER_IS_MS_BUFF_SRC(player)) ||
(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_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_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;
+ }
+
+ if (player->msg_posted) {
+ LOGE("error msg is already posted.");
+ return ret;
+ }
- timer = g_timer_new();
- g_timer_start(timer);
+ timer = g_timer_new();
+ g_timer_start(timer);
- GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
+ GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
- do {
- msg = gst_bus_timed_pop(bus, 100 * GST_MSECOND);
- if (msg) {
- if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
- GError *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;
- /* parse error code */
- gst_message_parse_error(msg, &error, NULL);
+ /* parse error code */
+ gst_message_parse_error(msg, &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);
+ 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);
- } else if (error) {
- LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
+ } else if (error) {
+ LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
- 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);
+ 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);
- }
- player->msg_posted = TRUE;
+ 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 */
+ /* rtsp case, async_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.
+ * It needs to send the event to the text sink seperately.
*/
- 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, gint64 position, gboolean internal_called)
+_mmplayer_gst_set_position(mmplayer_t *player, gint64 position, gboolean internal_called)
{
int ret = MM_ERROR_NONE;
gint64 pos_nsec = 0;
- gboolean accurated = FALSE;
+ gboolean accurate = FALSE;
GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
MMPLAYER_FENTER();
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;
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);
+ return (ret == MM_ERROR_PLAYER_NO_OP) ? MM_ERROR_NONE : ret;
}
if (!__mmplayer_gst_check_seekable(player))
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)) {
+ (_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");
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)
+ mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurate);
+ if (accurate)
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,
+ if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
GST_FORMAT_TIME, seek_flags,
GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
LOGE("failed to set position");
}
/* NOTE : store last seeking point to overcome some bad operation
- * (returning zero when getting current position) of some elements
- */
+ * (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. */
+ /* MSL should guarantee 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);
return MM_ERROR_NONE;
PENDING:
- player->pending_seek.is_pending = TRUE;
+ 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")",
}
int
-__mmplayer_gst_get_position(mm_player_t* player, 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;
/* NOTE : get last point to overcome some bad operation of some elements
*(returning zero when getting current position in paused state
- * and when failed to get postion during seeking
+ * and when failed to get position during seeking
*/
if ((current_state == MM_PLAYER_STATE_PAUSED) || (!ret)) {
LOGD("pos_nsec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_nsec), ret, current_state);
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. */
return MM_ERROR_PLAYER_NO_OP;
}
- if (format != MM_PLAYER_POS_FORMAT_PERCENT) {
- LOGW("Time format is not supported yet");
- return MM_ERROR_INVALID_ARGUMENT;
- }
-
if (content_size_time <= 0 || content_size_bytes <= 0) {
LOGW("there is no content size");
return MM_ERROR_NONE;
}
- if (__mmplayer_gst_get_position(player, &position) != MM_ERROR_NONE) {
+ 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",
- 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:
{
g_object_set(src_elem, "stream-type", stream_type,
"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;
+ int ret = MM_ERROR_NONE;
+ 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;
+ }
+
+ if (!MMPLAYER_USE_DECODEBIN(player)) {
+ ret = _mmplayer_gst_build_pipeline_with_src(player);
+ if (ret != MM_ERROR_NONE)
+ goto ERROR;
+
+ if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("Failed to change state of uridecodebin3 element");
+ goto ERROR;
+ }
+ goto DONE;
+ }
+
+ 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 %s to pipeline", GST_ELEMENT_NAME(element));
+ 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;
+ }
+
+DONE:
+ 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;
}