subtitle cleanup by yejin
authorYounghwan Ahn <younghwan_.an@samsung.com>
Thu, 3 Jan 2013 06:39:27 +0000 (15:39 +0900)
committerYounghwan Ahn <younghwan_.an@samsung.com>
Thu, 3 Jan 2013 06:39:27 +0000 (15:39 +0900)
Change-Id: I955ee19ad115cc7296fcc8bc93b210f777fdd037

configure.ac
packaging/libmm-player.spec
src/Makefile.am
src/include/mm_player_priv.h
src/include/mm_player_utils.h
src/mm_player_priv.c
src/mm_player_utils.c

index 80e3347..4070017 100755 (executable)
@@ -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)
index 0bd76b0..ac0220f 100644 (file)
@@ -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
 
index e2a2a28..8e1523e 100755 (executable)
@@ -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)
index cdb5dc6..25254eb 100755 (executable)
@@ -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;
index 07f4f47..624df44 100755 (executable)
@@ -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
index 459fcac..4d461d2 100755 (executable)
@@ -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, &current_pos );
-                       if ( !ret )
+                       if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &current_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;
 
index 87438a4..41c8f00 100755 (executable)
@@ -26,6 +26,8 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <unicode/ucsdet.h>
+
 #include <mm_debug.h>
 #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;
+}
+