From d8b47d47593f850df4b72b8ea5e0d971f76d54f7 Mon Sep 17 00:00:00 2001 From: Younghwan Ahn Date: Thu, 3 Jan 2013 15:39:27 +0900 Subject: [PATCH] subtitle cleanup by yejin Change-Id: I955ee19ad115cc7296fcc8bc93b210f777fdd037 --- configure.ac | 4 + packaging/libmm-player.spec | 2 +- src/Makefile.am | 6 +- src/include/mm_player_priv.h | 24 +- src/include/mm_player_utils.h | 2 + src/mm_player_priv.c | 510 ++++++++++++++++++++++-------------------- src/mm_player_utils.c | 66 ++++++ 7 files changed, 355 insertions(+), 259 deletions(-) diff --git a/configure.ac b/configure.ac index 80e3347..4070017 100755 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,10 @@ PKG_CHECK_MODULES(AUDIOSESSIONMGR, audio-session-mgr) AC_SUBST(AUDIOSESSIONMGR_CFLAGS) AC_SUBST(AUDIOSESSIONMGR_LIBS) +PKG_CHECK_MODULES(ICU, icu-i18n) +AC_SUBST(ICU_CFLAGS) +AC_SUBST(ICU_LIBS) + PKG_CHECK_MODULES(INIPARSER, iniparser) AC_SUBST(INIPARSER_CFLAGS) AC_SUBST(INIPARSER_LIBS) diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index 0bd76b0..ac0220f 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -21,7 +21,7 @@ BuildRequires: pkgconfig(mmutil-imgp) BuildRequires: pkgconfig(audio-session-mgr) BuildRequires: pkgconfig(iniparser) BuildRequires: pkgconfig(vconf) - +BuildRequires: pkgconfig(icu-i18n) BuildRoot: %{_tmppath}/%{name}-%{version}-build diff --git a/src/Makefile.am b/src/Makefile.am index e2a2a28..8e1523e 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,7 +27,8 @@ libmmfplayer_la_CFLAGS = -I$(srcdir)/include \ $(MMSESSION_CFLAGS) \ $(MMSOUND_CFLAGS) \ $(AUDIOSESSIONMGR_CFLAGS) \ - $(VCONF_CFLAGS) + $(VCONF_CFLAGS) \ + $(ICU_CFLAGS) noinst_HEADERS = include/mm_player_utils.h \ include/mm_player_ini.h \ @@ -48,7 +49,8 @@ libmmfplayer_la_LIBADD = $(GST_LIBS) \ $(MMSESSION_LIBS) \ $(MMSOUND_LIBS) \ $(AUDIOSESSIONMGR_LIBS) \ - $(VCONF_LIBS) + $(VCONF_LIBS) \ + $(ICU_LIBS) libmmfplayer_la_CFLAGS += $(MMLOG_CFLAGS) -DMMF_LOG_OWNER=0x008 -DMMF_DEBUG_PREFIX=\"MMF-PLAYER\" -D_INTERNAL_SESSION_MANAGER_ libmmfplayer_la_LIBADD += $(MMLOG_LIBS) diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index cdb5dc6..25254eb 100755 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -141,6 +141,7 @@ enum MainElementID { MMPLAYER_M_PIPE = 0, /* NOTE : MMPLAYER_M_PIPE should be zero */ MMPLAYER_M_SRC, + MMPLAYER_M_SUBSRC, /* it could be a decodebin or could be a typefind. depends on player ini */ MMPLAYER_M_AUTOPLUG, @@ -164,6 +165,7 @@ enum MainElementID MMPLAYER_M_Q1, MMPLAYER_M_Q2, MMPLAYER_M_DEMUX, + MMPLAYER_M_SUBPARSE, MMPLAYER_M_NUM }; @@ -197,28 +199,14 @@ enum VideoElementID enum TextElementID { MMPLAYER_T_BIN = 0, /* NOTE : MMPLAYER_V_BIN should be zero */ - MMPLAYER_T_QUEUE, + MMPLAYER_T_TEXT_QUEUE, + MMPLAYER_T_VIDEO_QUEUE, + MMPLAYER_T_VIDEO_CONVERTER, MMPLAYER_T_OVERLAY, MMPLAYER_T_SINK, MMPLAYER_T_NUM }; -/* subtitle pipeline's element id */ -enum SubtitleElementID -{ - MMPLAYER_SUB_PIPE = 0, /* NOTE : MMPLAYER_SUB_PIPE should be zero */ - MMPLAYER_SUB_SRC, - MMPLAYER_SUB_QUEUE, - MMPLAYER_SUB_SUBPARSE, - MMPLAYER_SUB_TEXTRENDER, - MMPLAYER_SUB_FLIP, - MMPLAYER_SUB_CONV1, - MMPLAYER_SUB_CONV2, - MMPLAYER_SUB_SCALE, - MMPLAYER_SUB_SINK, - MMPLAYER_SUB_NUM -}; - /* midi main pipeline's element id */ enum MidiElementID { @@ -310,7 +298,6 @@ typedef struct { GstTagList *tag_list; MMPlayerGstElement *mainbin; - MMPlayerGstElement *subtitlebin; MMPlayerGstElement *audiobin; MMPlayerGstElement *videobin; MMPlayerGstElement *textbin; @@ -617,6 +604,7 @@ typedef struct { gboolean keep_detecting_vcodec; gboolean play_subtitle; + gboolean use_textoverlay; /* PD downloader message callback and param */ MMMessageCallback pd_msg_cb; diff --git a/src/include/mm_player_utils.h b/src/include/mm_player_utils.h index 07f4f47..624df44 100755 --- a/src/include/mm_player_utils.h +++ b/src/include/mm_player_utils.h @@ -268,6 +268,8 @@ int util_is_midi_type_by_file(const char *file_path); char** util_get_cookie_list ( const char *cookies ); bool util_check_valid_url ( const char *proxy ); +char* util_get_charset(const char *file_path); + #ifdef __cplusplus } #endif diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 459fcac..4d461d2 100755 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -87,7 +87,6 @@ gulong ahs_appsrc_cb_probe_id = 0; #define MMPLAYER_USE_FILE_FOR_BUFFERING(player) (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && (PLAYER_INI()->http_file_buffer_path) && (strlen(PLAYER_INI()->http_file_buffer_path) > 0) ) -#define MMPLAYER_PLAY_SUBTITLE(player) ((player)->play_subtitle) #define LAZY_PAUSE_TIMEOUT_MSEC 700 @@ -115,7 +114,7 @@ static int __mmplayer_get_state(mm_player_t* player); static int __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type); static int __mmplayer_gst_create_audio_pipeline(mm_player_t* player); static int __mmplayer_gst_create_text_pipeline(mm_player_t* player); -static int __mmplayer_gst_create_subtitle_pipeline(mm_player_t* player); +static int __mmplayer_gst_create_subtitle_src(mm_player_t* player); static int __mmplayer_gst_create_pipeline(mm_player_t* player); static int __mmplayer_gst_destroy_pipeline(mm_player_t* player); static int __mmplayer_gst_element_link_bucket(GList* element_bucket); @@ -2245,6 +2244,12 @@ __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last player->audiosink_linked = 1; debug_msg("player->audsink_linked set to 1\n"); + sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" ); + if ( !sinkpad ) + { + debug_error("failed to get pad from sinkbin\n"); + goto ERROR; + } } else if (strstr(name, "video")) { @@ -2286,6 +2291,12 @@ __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last player->videosink_linked = 1; debug_msg("player->videosink_linked set to 1\n"); + sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" ); + if ( !sinkpad ) + { + debug_error("failed to get pad from sinkbin\n"); + goto ERROR; + } } else if (strstr(name, "text")) { @@ -2313,6 +2324,13 @@ __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last player->textsink_linked = 1; debug_msg("player->textsink_linked set to 1\n"); + + sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "text_sink" ); + if ( !sinkpad ) + { + debug_error("failed to get pad from sinkbin\n"); + goto ERROR; + } } else { @@ -2336,14 +2354,6 @@ __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last goto ERROR; } - sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" ); - - if ( !sinkpad ) - { - debug_error("failed to get pad from sinkbin\n"); - goto ERROR; - } - /* link */ if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) ) { @@ -2368,7 +2378,6 @@ __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last debug_log("linking sink bin success\n"); - /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in * streaming task. if the task blocked, then buffer will not flow to the next element * ( autoplugging element ). so this is special hack for streaming. please try to remove it @@ -2850,6 +2859,22 @@ if ( ! x_bin[x_id].gst )\ goto ERROR;\ }\ +#define MMPLAYER_CREATE_ELEMENT_ADD_BIN(x_bin, x_id, x_factory, x_name, y_bin) \ +x_bin[x_id].id = x_id;\ +x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\ +if ( ! x_bin[x_id].gst )\ +{\ + debug_critical("failed to create %s \n", x_factory);\ + goto ERROR;\ +}\ +if( !gst_bin_add(GST_BIN(y_bin), GST_ELEMENT(x_bin[x_id].gst)))\ +{\ + debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s] to bin [%s] failed\n",\ + GST_ELEMENT_NAME(GST_ELEMENT(x_bin[x_id].gst)),\ + GST_ELEMENT_NAME(GST_ELEMENT(y_bin) ) );\ + goto ERROR;\ +}\ + /* macro for code readability. just for sinkbin-creation functions */ #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket) \ do \ @@ -3559,64 +3584,151 @@ static int __mmplayer_gst_create_text_pipeline(mm_player_t* player) player->pipeline->textbin = textbin; /* fakesink */ - MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_SINK, "fakesink", "text_sink", TRUE); + if (player->use_textoverlay) + { + debug_log ("use textoverlay for displaying \n"); - g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "sync", TRUE, NULL); - g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "async", FALSE, NULL); - g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "signal-handoffs", TRUE, NULL); + MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_TEXT_QUEUE, "queue", "text_t_queue", textbin[MMPLAYER_T_BIN].gst); - MMPLAYER_SIGNAL_CONNECT( player, - G_OBJECT(textbin[MMPLAYER_T_SINK].gst), - "handoff", - G_CALLBACK(__mmplayer_update_subtitle), - (gpointer)player ); + MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_QUEUE, "queue", "text_v_queue", textbin[MMPLAYER_T_BIN].gst); - __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_SINK].gst)); + MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_VIDEO_CONVERTER, "fimcconvert", "text_v_converter", textbin[MMPLAYER_T_BIN].gst); - /* adding created elements to bin */ - debug_log("adding created elements to bin\n"); - if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket )) + MMPLAYER_CREATE_ELEMENT_ADD_BIN(textbin, MMPLAYER_T_OVERLAY, "textoverlay", "text_overlay", textbin[MMPLAYER_T_BIN].gst); + + if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_QUEUE].gst, "src", textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "sink")) + { + debug_error("failed to link queue and converter\n"); + goto ERROR; + } + + if (!gst_element_link_pads (textbin[MMPLAYER_T_VIDEO_CONVERTER].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "video_sink")) + { + debug_error("failed to link queue and textoverlay\n"); + goto ERROR; + } + + if (!gst_element_link_pads (textbin[MMPLAYER_T_TEXT_QUEUE].gst, "src", textbin[MMPLAYER_T_OVERLAY].gst, "text_sink")) + { + debug_error("failed to link queue and textoverlay\n"); + goto ERROR; + } + + } + else { - debug_error("failed to add elements\n"); - goto ERROR; + debug_log ("use subtitle message for displaying \n"); + + MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_TEXT_QUEUE, "queue", "text_queue", TRUE); + + MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_SINK, "fakesink", "text_sink", TRUE); + + g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "sync", TRUE, NULL); + g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "async", FALSE, NULL); + g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "signal-handoffs", TRUE, NULL); + + MMPLAYER_SIGNAL_CONNECT( player, + G_OBJECT(textbin[MMPLAYER_T_SINK].gst), + "handoff", + G_CALLBACK(__mmplayer_update_subtitle), + (gpointer)player ); + + if (!player->play_subtitle) + { + debug_log ("add textbin sink as sink element of whole pipeline.\n"); + __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_SINK].gst)); + } + + /* adding created elements to bin */ + debug_log("adding created elements to bin\n"); + if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket )) + { + debug_error("failed to add elements\n"); + goto ERROR; + } + + /* linking elements in the bucket by added order. */ + debug_log("Linking elements in the bucket by added order.\n"); + if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 ) + { + debug_error("failed to link elements\n"); + goto ERROR; + } + + /* done. free allocated variables */ + g_list_free(element_bucket); } - /* linking elements in the bucket by added order. */ - debug_log("Linking elements in the bucket by added order.\n"); - if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 ) + if (textbin[MMPLAYER_T_TEXT_QUEUE].gst) { - debug_error("failed to link elements\n"); - goto ERROR; - } + pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_TEXT_QUEUE].gst), "sink"); + if (!pad) + { + debug_error("failed to get text pad of textbin\n"); + goto ERROR; + } - /* get first element's sinkpad for creating ghostpad */ - first_element = (MMPlayerGstElement *)element_bucket->data; + ghostpad = gst_ghost_pad_new("text_sink", pad); + if (!ghostpad) + { + debug_error("failed to create ghostpad of textbin\n"); + goto ERROR; + } - pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink"); - if ( ! pad ) - { - debug_error("failed to get pad from first element of textbin\n"); - goto ERROR; + if ( FALSE == gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad) ) + { + debug_error("failed to add ghostpad to textbin\n"); + goto ERROR; + } } - ghostpad = gst_ghost_pad_new("sink", pad); - if ( ! ghostpad ) + if (textbin[MMPLAYER_T_VIDEO_QUEUE].gst) { - debug_error("failed to create ghostpad\n"); - goto ERROR; + pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_VIDEO_QUEUE].gst), "sink"); + if (!pad) + { + debug_error("failed to get video pad of textbin\n"); + goto ERROR; + } + + ghostpad = gst_ghost_pad_new("video_sink", pad); + if (!ghostpad) + { + debug_error("failed to create ghostpad of textbin\n"); + goto ERROR; + } + + if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) + { + debug_error("failed to add ghostpad to textbin\n"); + goto ERROR; + } } - if ( FALSE == gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad) ) + if (textbin[MMPLAYER_T_OVERLAY].gst) { - debug_error("failed to add ghostpad to textbin\n"); - goto ERROR; - } + pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_OVERLAY].gst), "src"); + if (!pad) + { + debug_error("failed to get src pad of textbin\n"); + goto ERROR; + } - gst_object_unref(pad); + ghostpad = gst_ghost_pad_new("src", pad); + if (!ghostpad) + { + debug_error("failed to create ghostpad of textbin\n"); + goto ERROR; + } + if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) + { + debug_error("failed to add ghostpad to textbin\n"); + goto ERROR; + } + } - /* done. free allocated variables */ - g_list_free(element_bucket); + gst_object_unref(pad); debug_fleave(); @@ -3670,24 +3782,24 @@ ERROR: static int -__mmplayer_gst_create_subtitle_pipeline(mm_player_t* player) +__mmplayer_gst_create_subtitle_src(mm_player_t* player) { - MMPlayerGstElement* subtitlebin = NULL; + MMPlayerGstElement* mainbin = NULL; MMHandleType attrs = 0; + GstElement * pipeline = NULL; + GstElement *subsrc = NULL; + GstElement *subparse = NULL; + GstPad *sinkpad = NULL; gchar *subtitle_uri =NULL; - GList*element_bucket = NULL; - - #define USE_MESSAGE_FOR_PLAYING_SUBTITLE -#ifndef USE_MESSAGE_FOR_PLAYING_SUBTITLE - void *xid = NULL; - gint width =0, height = 0; - gboolean silent=FALSE; -#endif + gchar *charset = NULL; debug_fenter(); /* get mainbin */ - return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED); + return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED); + + pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst; + mainbin = player->pipeline->mainbin; attrs = MMPLAYER_GET_ATTRS(player); if ( !attrs ) @@ -3705,104 +3817,74 @@ __mmplayer_gst_create_subtitle_pipeline(mm_player_t* player) debug_log("subtitle file path is [%s].\n", subtitle_uri); - /* alloc handles */ - subtitlebin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_SUB_NUM); - if ( !subtitlebin ) - { - debug_error("failed to allocate memory\n"); - return MM_ERROR_PLAYER_NO_FREE_SPACE; - } - - /* create bin */ - subtitlebin[MMPLAYER_SUB_PIPE].id = MMPLAYER_SUB_PIPE; - subtitlebin[MMPLAYER_SUB_PIPE].gst = gst_pipeline_new("subtitlebin"); - if ( !subtitlebin[MMPLAYER_SUB_PIPE].gst ) + /* create the subtitle source */ + subsrc = gst_element_factory_make("filesrc", "subtitle_source"); + if ( !subsrc ) { - debug_error("failed to create text pipeline\n"); + debug_error ( "failed to create filesrc element\n" ); goto ERROR; } - player->pipeline->subtitlebin = subtitlebin; + g_object_set(G_OBJECT (subsrc), "location", subtitle_uri, NULL); - /* create the text file source */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SRC, "filesrc", "subtitle_source", TRUE); - g_object_set(G_OBJECT (subtitlebin[MMPLAYER_SUB_SRC].gst), "location", subtitle_uri, NULL); + mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC; + mainbin[MMPLAYER_M_SUBSRC].gst = subsrc; - /* queue */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_QUEUE, "queue", NULL, TRUE); + if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc)) + { + debug_warning("failed to add queue\n"); + goto ERROR; + } /* subparse */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SUBPARSE, "subparse", "subtitle_parser", TRUE); - -#ifndef USE_MESSAGE_FOR_PLAYING_SUBTITLE - /* textrender */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_TEXTRENDER, "textrender", "subtitle_render", TRUE); - - mm_attrs_get_int_by_name(attrs,"width", &width); - mm_attrs_get_int_by_name(attrs,"height", &height); - mm_attrs_get_int_by_name(attrs,"silent", &silent); - g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"width", width, NULL); - g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"height", height, NULL); - g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"silent", silent, NULL); - - debug_log ( "subtitle winow size is [%dX%d].\n", width, height ); - debug_log ( "subtitle silent is [%d].\n", silent ); - - /* converter1 */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_CONV1, "ffmpegcolorspace", "subtitle_converter1", TRUE); - - /* videofliper */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_FLIP, "videoflip", "subtitle_fliper", TRUE); + subparse = gst_element_factory_make("subparse", "subtitle_parser"); + if ( !subparse ) + { + debug_error ( "failed to create subparse element\n" ); + goto ERROR; + } - /* converter2 */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_CONV2, "ffmpegcolorspace", "subtitle_converter2", TRUE); + charset = util_get_charset(subtitle_uri); + if (charset) + { + debug_log ("detected charset is %s\n", charset ); + g_object_set (G_OBJECT (subparse), "subtitle-encoding", charset, NULL); + } - /* text sink */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SINK, "ximagesink", "subtitle_sink", TRUE); + mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE; + mainbin[MMPLAYER_M_SUBPARSE].gst = subparse; - mm_attrs_get_data_by_name(attrs, "xid", &xid); - if ( xid ) + if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse)) { - debug_log("setting subtitle xid = %d\n", *(int*)xid); - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(subtitlebin[MMPLAYER_SUB_SINK].gst), *(int*)xid); + debug_warning("failed to add subparse\n"); + goto ERROR; } - else + + if (!gst_element_link_pads (subsrc, "src", subparse, "sink")) { - /* FIXIT : is it error case? */ - debug_warning("still we don't have xid on player attribute. create it's own surface.\n"); + debug_warning("failed to link subsrc and subparse\n"); + goto ERROR; } -#else - /* text sink */ - MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SINK, "fakesink", "subtitle_sink", TRUE); - - g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "sync", TRUE, NULL); - g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "async", FALSE, NULL); - g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "signal-handoffs", TRUE, NULL); - MMPLAYER_SIGNAL_CONNECT( player, - G_OBJECT(subtitlebin[MMPLAYER_SUB_SINK].gst), - "handoff", - G_CALLBACK(__mmplayer_update_subtitle), - (gpointer)player ); -#endif + player->play_subtitle = TRUE; + debug_log ("play subtitle using subtitle file\n"); - /* adding created elements to bin */ - if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(subtitlebin[MMPLAYER_SUB_PIPE].gst), element_bucket) ) - { - debug_error("failed to add elements\n"); + if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) + { + debug_error("failed to create textbin. continuing without text\n"); goto ERROR; - } + } - /* Linking elements in the bucket by added order */ - if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 ) - { - debug_error("failed to link elements\n"); + if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(player->pipeline->textbin[MMPLAYER_T_BIN].gst))) + { + debug_warning("failed to add textbin\n"); goto ERROR; - } - - /* done. free allocated variables */ - g_list_free(element_bucket); + } - player->play_subtitle = TRUE; + if (!gst_element_link_pads (subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink")) + { + debug_warning("failed to link subparse and textbin\n"); + goto ERROR; + } debug_fleave(); @@ -3810,20 +3892,6 @@ __mmplayer_gst_create_subtitle_pipeline(mm_player_t* player) ERROR: - debug_error("ERROR : releasing text pipeline\n"); - - g_list_free( element_bucket ); - - /* release subtitlebin with it's childs */ - if ( subtitlebin[MMPLAYER_SUB_PIPE].gst ) - { - gst_object_unref(GST_OBJECT(subtitlebin[MMPLAYER_SUB_PIPE].gst)); - } - - MMPLAYER_FREEIF( subtitlebin ); - - player->pipeline->subtitlebin = NULL; - return MM_ERROR_PLAYER_INTERNAL; } @@ -3868,7 +3936,6 @@ __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, return ret; } - static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position) { GstEvent* event = NULL; @@ -3879,12 +3946,12 @@ static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int debug_fenter(); /* check player and subtitlebin are created */ - return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED ); - return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player), MM_ERROR_PLAYER_NOT_INITIALIZED ); + return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED ); + return_val_if_fail ( player->play_subtitle, MM_ERROR_NOT_SUPPORT_API ); if (position == 0) { - debug_log("adjusted values is 0, no need to adjust subtitle position.\n"); + debug_log ("nothing to do\n"); return MM_ERROR_NONE; } @@ -3892,33 +3959,22 @@ static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int { case MM_PLAYER_POS_FORMAT_TIME: { - GstFormat fmt = GST_FORMAT_TIME; /* check current postion */ - ret = gst_element_query_position( GST_ELEMENT(player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst), &fmt, ¤t_pos ); - if ( !ret ) + if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, ¤t_pos )) { - debug_warning("fail to query current postion.\n"); - return MM_ERROR_PLAYER_SEEK; - } - else - { - adusted_pos = current_pos + ((gint64)position * G_GINT64_CONSTANT(1000000)); - if (adusted_pos < 0) - adusted_pos = G_GINT64_CONSTANT(0); - debug_log("adjust subtitle postion : %lu -> %lu [msec]\n", GST_TIME_AS_MSECONDS(current_pos), GST_TIME_AS_MSECONDS(adusted_pos)); + debug_error("failed to get position"); + return MM_ERROR_PLAYER_INTERNAL; } - event = gst_event_new_seek (1.0, GST_FORMAT_TIME, - ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ), - GST_SEEK_TYPE_SET, adusted_pos, - GST_SEEK_TYPE_SET, -1); - } - break; + adusted_pos = (gint64)current_pos + ((gint64)position * G_GINT64_CONSTANT(1000000)); + if (adusted_pos < 0) + adusted_pos = G_GUINT64_CONSTANT(0); + debug_log("adjust subtitle postion : %lu -> %lu [msec]\n", GST_TIME_AS_MSECONDS(current_pos), GST_TIME_AS_MSECONDS(adusted_pos)); - case MM_PLAYER_POS_FORMAT_PERCENT: - { - debug_warning("percent format is not supported yet.\n"); - return MM_ERROR_INVALID_ARGUMENT; + event = gst_event_new_seek (1.0, GST_FORMAT_TIME, + ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ), + GST_SEEK_TYPE_SET, adusted_pos, + GST_SEEK_TYPE_SET, -1); } break; @@ -3932,23 +3988,21 @@ static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int /* keep ref to the event */ gst_event_ref (event); - debug_log("sending event[%s] to sink element [%s]\n", - GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst) ); + debug_log("sending event[%s] to subparse element [%s]\n", + GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst) ); - if ( ret = gst_element_send_event (player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst, event) ) + if (gst_element_send_event (player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst, event)) { - debug_log("sending event[%s] to sink element [%s] success!\n", - GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst) ); + debug_log("sending event[%s] to subparse element [%s] success!\n", + GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst) ); } /* unref to the event */ gst_event_unref (event); - debug_fleave(); return MM_ERROR_NONE; - } static void @@ -4551,21 +4605,16 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ } player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player); - /* Note : check whether subtitle atrribute uri is set. If uri is set, then create the text pipeline */ + /* Note : check whether subtitle atrribute uri is set. If uri is set, then tyr to play subtitle file */ if ( __mmplayer_check_subtitle ( player ) ) { - debug_log("try to create subtitle pipeline \n"); - - if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_pipeline(player) ) - debug_error("fail to create subtitle pipeline") - else - debug_log("subtitle pipeline is created successfully\n"); + if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_src(player) ) + debug_error("fail to create subtitle src\n") } /* set sync handler to get tag synchronously */ gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player); - /* finished */ gst_object_unref(GST_OBJECT(bus)); g_list_free(element_bucket); @@ -4676,7 +4725,6 @@ __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @ MMPlayerGstElement* audiobin = player->pipeline->audiobin; MMPlayerGstElement* videobin = player->pipeline->videobin; MMPlayerGstElement* textbin = player->pipeline->textbin; - MMPlayerGstElement* subtitlebin = player->pipeline->subtitlebin; GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst)); gst_bus_set_sync_handler (bus, NULL, NULL); @@ -4707,7 +4755,6 @@ __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @ MMPLAYER_FREEIF( audiobin ); MMPLAYER_FREEIF( videobin ); MMPLAYER_FREEIF( textbin ); - MMPLAYER_FREEIF( subtitlebin); MMPLAYER_FREEIF( mainbin ); } @@ -4750,10 +4797,6 @@ static int __gst_realize(mm_player_t* player) // @ ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout); - if (MMPLAYER_PLAY_SUBTITLE(player)) - ret = __mmplayer_gst_set_state(player, - player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_READY, FALSE, timeout); - if ( ret != MM_ERROR_NONE ) { /* return error if failed to set state */ @@ -4901,11 +4944,6 @@ static int __gst_start(mm_player_t* player) // @ /* set pipeline state to PLAYING */ ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) ); - - if (MMPLAYER_PLAY_SUBTITLE(player)) - ret = __mmplayer_gst_set_state(player, - player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) ); - if (ret == MM_ERROR_NONE) { MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING); @@ -5004,10 +5042,6 @@ static int __gst_stop(mm_player_t* player) // @ ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout ); - if (MMPLAYER_PLAY_SUBTITLE(player)) - ret = __mmplayer_gst_set_state( player, - player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout ); - if ( !MMPLAYER_IS_STREAMING(player)) rewind = TRUE; } @@ -5045,9 +5079,6 @@ static int __gst_stop(mm_player_t* player) // @ /* wait for seek to complete */ change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND); - if (MMPLAYER_PLAY_SUBTITLE(player)) - change_ret = gst_element_get_state (player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, NULL, NULL, timeout * GST_SECOND); - if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL ) { MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY ); @@ -5082,10 +5113,6 @@ int __gst_pause(mm_player_t* player, gboolean async) // @ ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player)); - if (MMPLAYER_PLAY_SUBTITLE(player)) - ret = __mmplayer_gst_set_state(player, - player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player)); - if ( ret != MM_ERROR_NONE ) { debug_error("failed to set state to PAUSED\n"); @@ -5141,11 +5168,6 @@ int __gst_resume(mm_player_t* player, gboolean async) // @ timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player); ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout ); - - if (MMPLAYER_PLAY_SUBTITLE(player)) - ret = __mmplayer_gst_set_state(player, - player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PLAYING, async, timeout ); - if (ret != MM_ERROR_NONE) { debug_error("failed to set state to PLAYING\n"); @@ -5966,11 +5988,15 @@ _mmplayer_create_player(MMHandleType handle) // @ player->playback_rate = DEFAULT_PLAYBACK_RATE; player->no_more_pad = TRUE; + player->play_subtitle = FALSE; + player->use_textoverlay = FALSE; + /* set player state to null */ MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout; MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL ); debug_fleave(); + return MM_ERROR_NONE; ERROR: @@ -7489,7 +7515,7 @@ __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // mime = gst_structure_get_name(gst_caps_get_structure(caps, 0)); /* return if we got raw output */ - if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw") ||g_str_has_prefix(mime, "text/plain") ) + if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw") || g_str_has_prefix(mime, "text/plain") ||g_str_has_prefix(mime, "text/x-pango-markup")) { element = (GstElement*)gst_pad_get_parent(pad); @@ -7501,7 +7527,6 @@ __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // * Anyway, currentely raw-queue seems not necessary. */ #if 1 - /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder * has linked. if so, we need to add queue for quality of output. note that * decodebin also has same problem. @@ -7510,9 +7535,9 @@ __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // klass = gst_element_factory_get_klass( gst_element_get_factory(element) ); /* add queue if needed */ - if( g_strrstr(klass, "Demux") || + if( (g_strrstr(klass, "Demux") || g_strrstr(klass, "Depayloader") || - g_strrstr(klass, "Parse") ) + g_strrstr(klass, "Parse")) && !g_str_has_prefix(mime, "text")) { debug_log("adding raw queue\n"); @@ -7573,7 +7598,6 @@ __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // gst_object_unref( GST_OBJECT(element)); element = NULL; - return TRUE; } @@ -9825,6 +9849,7 @@ ERROR: static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event ) { + GstEvent * event2 = NULL; GList *sinks = NULL; gboolean res = FALSE; @@ -9833,6 +9858,9 @@ __gst_send_event_to_sink( mm_player_t* player, GstEvent* event ) return_val_if_fail( player, FALSE ); return_val_if_fail ( event, FALSE ); + if ( player->play_subtitle && !player->use_textoverlay) + event2 = gst_event_copy((const GstEvent *)event); + sinks = player->sink_elements; while (sinks) { @@ -9860,19 +9888,27 @@ __gst_send_event_to_sink( mm_player_t* player, GstEvent* event ) /* Note : Textbin is not linked to the video or audio bin. * It needs to send the event to the text sink seperatelly. */ - if ( MMPLAYER_PLAY_SUBTITLE(player) ) + if ( player->play_subtitle && !player->use_textoverlay) { - GstElement *subtitle_sink = GST_ELEMENT_CAST (player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst); + GstElement *text_sink = GST_ELEMENT_CAST (player->pipeline->textbin[MMPLAYER_T_SINK].gst); - if ( (res != gst_element_send_event (subtitle_sink, event)) ) + if (GST_IS_ELEMENT(text_sink)) { - debug_error("sending event[%s] to subtitle sink element [%s] failed!\n", - GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(subtitle_sink) ); - } - else - { - debug_log("sending event[%s] to subtitle sink element [%s] success!\n", - GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(subtitle_sink) ); + /* keep ref to the event */ + gst_event_ref (event2); + + if ( (res != gst_element_send_event (text_sink, event2)) ) + { + debug_error("sending event[%s] to subtitle sink element [%s] failed!\n", + GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) ); + } + else + { + debug_log("sending event[%s] to subtitle sink element [%s] success!\n", + GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink) ); + } + + gst_event_unref (event2); } } @@ -9996,7 +10032,6 @@ int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent) /* check player handle */ return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED ); - return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player), MM_ERROR_PLAYER_NOT_INITIALIZED ); player->is_subtitle_off = silent; @@ -10016,7 +10051,6 @@ int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent) /* check player handle */ return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED ); - return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player), MM_ERROR_PLAYER_NOT_INITIALIZED ); *silent = player->is_subtitle_off; diff --git a/src/mm_player_utils.c b/src/mm_player_utils.c index 87438a4..41c8f00 100755 --- a/src/mm_player_utils.c +++ b/src/mm_player_utils.c @@ -26,6 +26,8 @@ #include #include #include +#include + #include #include "mm_player_utils.h" @@ -378,3 +380,67 @@ util_factory_rank_compare(GstPluginFeature *f1, GstPluginFeature *f2) // @ return (gst_plugin_feature_get_rank(f2)+f2_rank_inc) - (gst_plugin_feature_get_rank(f1)+f1_rank_inc ); } + +char* +util_get_charset(const char *file_path) +{ + UCharsetDetector* ucsd; + const UCharsetMatch* ucm; + UErrorCode status = U_ZERO_ERROR; + + const char* charset = NULL; + char *buf = NULL; + FILE* fin; + + fin = fopen(file_path, "r"); + if (!fin) + { + debug_error("fail to open file %s\n", file_path); + return NULL; + } + + ucsd = ucsdet_open( &status ); + if( U_FAILURE(status) ) { + debug_error("fail to ucsdet_open\n"); + return NULL; + } + + ucsdet_enableInputFilter( ucsd, TRUE ); + + buf = g_malloc(1024*1024); + if (!buf) + { + debug_error("fail to alloc\n"); + goto done; + } + + fread( buf, 1, 1024*1024, fin ); + fclose(fin); + + ucsdet_setText( ucsd, buf, strlen(buf), &status ); + if( U_FAILURE(status) ) { + debug_error("fail to ucsdet_setText\n"); + goto done; + } + + ucm = ucsdet_detect( ucsd, &status ); + if( U_FAILURE(status) ) { + debug_error("fail to ucsdet_detect\n"); + goto done; + } + + charset = ucsdet_getName( ucm, &status ); + if( U_FAILURE(status) ) { + debug_error("fail to ucsdet_getName\n"); + goto done; + } + +done: + ucsdet_close( ucsd ); + + if (buf) + g_free(buf); + + return charset; +} + -- 2.7.4