========================================================================================== */
/*---------------------------------------------------------------------------
-| GLOBAL CONSTANT DEFINITIONS: |
----------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------
-| IMPORTED VARIABLE DECLARATIONS: |
----------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------
-| IMPORTED FUNCTION DECLARATIONS: |
----------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------
-| LOCAL #defines: |
----------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------
| LOCAL CONSTANT DEFINITIONS: |
---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------
-| LOCAL DATA TYPE DEFINITIONS: |
----------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------
-| GLOBAL VARIABLE DEFINITIONS: |
----------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------
-| LOCAL VARIABLE DEFINITIONS: |
----------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------
-| LOCAL FUNCTION PROTOTYPES: |
----------------------------------------------------------------------------*/
+#define MMPLAYER_TAG_INDENT 3
/*===========================================================================================
| |
| FUNCTION DEFINITIONS |
| |
========================================================================================== */
+#ifdef __DEBUG__
+static void
+print_tag(const GstTagList *list, const gchar *tag, gpointer unused)
+{
+ gint i, count;
+
+ count = gst_tag_list_get_tag_size(list, tag);
+
+ LOGD("count = %d", count);
+
+ for (i = 0; i < count; i++) {
+ gchar *str;
+
+ 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));
+ }
+
+ if (i == 0)
+ g_print(" %15s: %s", gst_tag_get_nick(tag), str);
+ else
+ g_print(" : %s", str);
+
+ g_free(str);
+ }
+}
+#endif
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_pad_index = 0;
+ gint active_index = 0;
MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst, TRUE);
- active_pad_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
- LOGD("current active pad index -%d", active_pad_index);
+ 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;
idx++;
}
}
- LOGD("active pad = %d, error src index = %d", active_pad_index, msg_src_pos);
+ LOGD("active pad = %d, error src index = %d", active_index, msg_src_pos);
}
- if (active_pad_index != msg_src_pos) {
+ if (active_index != msg_src_pos) {
LOGD("skip error because error is posted from no activated track");
return FALSE;
}
player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
src_element = GST_ELEMENT_CAST(message->src);
- if (!src_element)
- return MM_ERROR_PLAYER_INTERNAL;
-
src_element_name = GST_ELEMENT_NAME(src_element);
if (!src_element_name)
return MM_ERROR_PLAYER_INTERNAL;
LOGD("error code=%d, msg=%s, src element=%s, class=%s",
error->code, error->message, src_element_name, klass);
- if (!__mmplayer_check_error_posted_from_activated_track(player, src_element_name))
+ if (MMPLAYER_USE_DECODEBIN(player) &&
+ !__mmplayer_check_error_posted_from_activated_track(player, src_element_name))
return MM_ERROR_NONE;
switch (error->code) {
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));
msg_param.data = (void *)error->message;
- LOGE("-Msg src : [%s] Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]",
+ 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);
}
if (message->src) {
msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
- LOGE("-Msg src : [%s] Code : [%x] Error : [%s]",
+ LOGE("-Msg src : [%s] Code : [0x%x] Error : [%s]",
msg_src_element, msg_param.code, (char *)msg_param.data);
}
{
/* macro for better code readability */
-#define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
+#define MMPLAYER_UPDATE_TAG_STRING(gsttag, player, playertag) \
do { \
if (gst_tag_list_get_string(tag_list, gsttag, &string)) {\
if (string != NULL) { \
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_attrs_set_string_by_name(attribute, playertag, new_string); \
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, new_string, strlen(new_string), NULL); \
MMPLAYER_FREEIF(new_string); \
} else { \
- mm_attrs_set_string_by_name(attribute, playertag, string); \
+ mm_player_set_attribute((MMHandleType)player, NULL,\
+ playertag, string, strlen(string), NULL); \
} \
MMPLAYER_FREEIF(string); \
} \
} \
} while (0)
-#define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
+#define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, player, playertag) \
do { \
GstSample *sample = NULL;\
if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample)) {\
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);\
+ 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;\
} \
} while (0)
-#define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
+#define MMPLAYER_UPDATE_TAG_UINT(gsttag, player, playertag) \
do { \
if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint)) { \
if (v_uint) { \
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); \
+ 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_attrs_set_int_by_name(attribute, playertag, player->total_bitrate); \
+ 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_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate);\
+ 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_attrs_set_int_by_name(attribute, playertag, v_uint); \
+ mm_player_set_attribute((MMHandleType)player, NULL, playertag, v_uint, NULL); \
} \
v_uint = 0;\
} \
} \
} while (0)
-#define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
+#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_attrs_set_string_by_name(attribute, playertag, string);\
+ 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);\
} \
} while (0)
-#define MMPLAYER_UPDATE_TAG_DATE_TIME(gsttag, attribute, playertag) \
+#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_attrs_set_string_by_name(attribute, playertag, string);\
+ 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);\
} \
} while (0)
-#define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
- do { \
- 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;\
- } \
- } \
- } while (0)
-
-#define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
- do { \
- 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;
-
char *string = NULL;
guint v_uint = 0;
GDate *date = NULL;
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 (mm_attrs_commit_all(attrs))
- LOGE("failed to commit.");
-
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(mmplayer_t *player, GstMessage *message)
{
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:
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;
ret = _mmplayer_gst_set_position(player, player->pending_seek.pos, FALSE);
if (ret != MM_ERROR_NONE)
- LOGE("failed to seek pending postion. just keep staying current position.");
+ LOGE("failed to seek pending position. just keep staying current position.");
player->pending_seek.is_pending = false;
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");
/* dump state of all element */
_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);
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;
}
}
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;
}
{
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);
{
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;
if (gst_structure_get_int(gst_message_get_structure(msg), "num_buffers", &num_buffers)) {
LOGD("video_num_buffers : %d", num_buffers);
- mm_attrs_set_int_by_name(player->attrs, MM_PLAYER_VIDEO_BUFFER_TOTAL_SIZE, 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)) {
LOGD("num_of_vout_extra num buffers : %d", extra_num_buffers);
- mm_attrs_set_int_by_name(player->attrs, MM_PLAYER_VIDEO_BUFFER_EXTRA_SIZE, extra_num_buffers);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_BUFFER_EXTRA_SIZE, extra_num_buffers, NULL);
}
return;
}
}
/* 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 *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);
- 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(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(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 (mm_attrs_commit_all(attrs))
- LOGE("failed to commit.");
}
MMPLAYER_FLEAVE();
}
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)
{
mmplayer_t *player = (mmplayer_t *)(data);
break;
case GST_MESSAGE_ERROR:
+ _mmplayer_set_reconfigure_state(player, FALSE);
__mmplayer_gst_handle_error_message(player, msg);
break;
case GST_MESSAGE_ASYNC_DONE:
__mmplayer_gst_handle_async_done_message(player, msg);
break;
+ case GST_MESSAGE_STREAM_COLLECTION:
+ {
+ GstStreamCollection *collection = NULL;
+ LOGD("GST_MESSAGE_STREAM_COLLECTION : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
+
+ 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;
- #if 0 /* delete unnecessary logs */
+#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_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
+#endif
default:
break;
case GST_MESSAGE_TAG:
__mmplayer_gst_extract_tag_from_msg(player, message);
- #if 0 // debug
+#ifdef __DEBUG__
{
GstTagList *tags = NULL;
}
break;
}
- #endif
+#endif
break;
case GST_MESSAGE_DURATION_CHANGED:
__mmplayer_gst_handle_duration(player, message);
break;
+ 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.
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;
__mmplayer_gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data)
{
mmplayer_t *player = (mmplayer_t *)user_data;
- mmplayer_stream_type_e type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ 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;
+ stream_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;
+ stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
} else {
- LOGE("can not enter here");
+ 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: %"G_GUINT64_FORMAT, 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)
{
mmplayer_t *player = (mmplayer_t *)user_data;
- mmplayer_stream_type_e type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ 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;
+ stream_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;
+ stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
} else {
- LOGE("can not enter here");
+ 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_t *player = (mmplayer_t *)user_data;
- mmplayer_stream_type_e type = MM_PLAYER_STREAM_TYPE_DEFAULT;
+ 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;
+ stream_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;
+ stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
} else {
- LOGE("can not enter here");
+ LOGW("invalid seek-data signal from %s", GST_ELEMENT_NAME(element));
return TRUE;
}
- LOGD("type: %d, pos: %"G_GUINT64_FORMAT, type, position);
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
+ LOGD("stream type: %d, pos: %"G_GUINT64_FORMAT, stream_type, 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);
+ msg_param.union_type = MM_MSG_UNION_SEEK_DATA;
+ msg_param.seek_data.stream_type = stream_type;
+ msg_param.seek_data.offset = position;
+
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_PUSH_BUFFER_SEEK_DATA, &msg_param);
return TRUE;
}
_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);
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);
}
NEW_ELEMENT:
- /* excute new_element if created*/
+ /* execute new_element if created*/
if (new_element) {
LOGD("adding new element to pipeline");
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);
}
* [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
+ * [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");
+ LOGD("it seems pad caps is directly used for autoplugging. removing fakesink now");
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.
return element;
}
+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)
{
+#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 = _mmplayer_get_cookie_list((const char *)cookies))) {
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);
{
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;
}
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)) {
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");
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)) ||
return ret;
}
- if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_decoded_cb) &&
- (!player->pipeline->videobin) && (!player->pipeline->audiobin))
- return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
+ 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;
+ }
MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
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) {
}
/* 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) {
GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
{
int ret = MM_ERROR_NONE;
gint64 pos_nsec = 0;
- gboolean accurated = FALSE;
+ gboolean accurate = FALSE;
GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
MMPLAYER_FENTER();
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;
*/
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);
/* 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);
int
_mmplayer_gst_build_es_pipeline(mmplayer_t *player)
{
- MMHandleType attrs = 0;
-
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;
- }
-
SECURE_LOGD("uri : %s", player->profile.uri);
- mm_attrs_set_int_by_name(attrs, "profile_prepare_async", TRUE);
- if (mm_attrs_commit_all(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();
}
int
+_mmplayer_gst_build_pipeline_with_src(mmplayer_t *player)
+{
+ mmplayer_gst_element_t *mainbin = NULL;
+ GstElement *autoplug_elem = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ mainbin = player->pipeline->mainbin;
+
+ LOGD("uri type %d", player->profile.uri_type);
+
+ 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->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) {
+ g_strlcpy(player->profile.uri, "appsrc://", MM_MAX_URL_LEN);
+ }
+
+ autoplug_elem = __mmplayer_gst_make_uridecodebin(player);
+ if (!autoplug_elem) {
+ LOGE("failed to create uridecodebin3 element");
+ goto ERROR;
+ }
+
+ LOGD("autoplug elem is created %s", GST_ELEMENT_NAME(autoplug_elem));
+ mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
+ mainbin[MMPLAYER_M_AUTOPLUG].gst = autoplug_elem;
+
+ if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), autoplug_elem)) {
+ LOGE("failed to add uridecodebin to pipeline");
+ goto ERROR;
+ }
+
+ /* FIXME: required ?*/
+ /* create fakesink element for keeping the pipeline state PAUSED. if needed */
+ mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
+ mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
+
+ if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
+ LOGE("failed to create fakesink");
+ goto ERROR;
+ }
+ GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
+
+ /* take ownership of fakesink. we are reusing it */
+ gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
+
+ if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
+ LOGE("failed to add fakesink to bin");
+ gst_object_unref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
+ goto ERROR;
+ }
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+
+ERROR:
+
+ if (mainbin[MMPLAYER_M_AUTOPLUG].gst)
+ gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_AUTOPLUG].gst));
+
+ if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
+ gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
+
+ mainbin[MMPLAYER_M_AUTOPLUG].gst = NULL;
+ mainbin[MMPLAYER_M_SRC_FAKESINK].gst = NULL;
+
+ return MM_ERROR_PLAYER_INTERNAL;
+}
+
+int
_mmplayer_gst_build_pipeline(mmplayer_t *player)
{
mmplayer_gst_element_t *mainbin = NULL;
GstElement *src_elem = NULL;
GstElement *autoplug_elem = NULL;
GList *element_bucket = NULL;
- MMHandleType attrs = 0;
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 */
}
/* 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;
}
- 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();
void
_mmplayer_activate_next_source(mmplayer_t *player, GstState target)
{
+ int ret = MM_ERROR_NONE;
mmplayer_gst_element_t *mainbin = NULL;
MMMessageParamType msg_param = {0,};
GstElement *element = NULL;
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("no source element was created");
}
if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
- LOGE("failed to add sinkbin to pipeline");
+ LOGE("failed to add %s to pipeline", GST_ELEMENT_NAME(element));
gst_object_unref(GST_OBJECT(element));
element = NULL;
goto ERROR;
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;
- }
-
- if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
- if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
- LOGE("Failed to change state of decodebin");
+ if (MMPLAYER_IS_HTTP_STREAMING(player)) {
+ if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) { // ????
+ LOGE("Failed to change state of src element");
goto ERROR;
}
} else {
- if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
- LOGE("Failed to change state of src element");
+ if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("Failed to change state of decodebin");
goto ERROR;
}
}
+ 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();
ERROR:
if (player) {
- MMPLAYER_PLAYBACK_UNLOCK(player);
-
+ _mmplayer_set_reconfigure_state(player, FALSE);
if (!player->msg_posted) {
MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
player->msg_posted = TRUE;