diff --git a/ChangeLog b/ChangeLog index 2be910d800..93ca741957 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2006-05-29 Tim-Philipp Müller + + Patch by: Young-Ho Cha + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (gst_play_base_bin_init), (gst_play_base_bin_dispose), + (set_encoding_element), (decodebin_element_added_cb), + (decodebin_element_removed_cb), (setup_subtitle), (setup_source), + (gst_play_base_bin_set_property), (gst_play_base_bin_get_property): + * gst/playback/gstplaybasebin.h: + Add 'subtitle-encoding' property to playbin, so applications can + force a subtitle encoding for non-UTF8 subtitles (#342268). + + * gst/subparse/gstsubparse.c: (gst_sub_parse_class_init), + (gst_sub_parse_set_property): + Rename recently-added 'encoding' property to 'subtitle-encoding' + (so it can be proxied by playbin/decodebin in a generic way + with less danger of false positives). + 2006-05-29 Michael Smith * gst/audioconvert/gstaudioconvert.c: (make_lossless_changes), diff --git a/gst/playback/gstplaybasebin.c b/gst/playback/gstplaybasebin.c index b8d1e57544..9fcbc0a1e0 100644 --- a/gst/playback/gstplaybasebin.c +++ b/gst/playback/gstplaybasebin.c @@ -71,7 +71,8 @@ enum ARG_SOURCE, ARG_VIDEO, ARG_AUDIO, - ARG_TEXT + ARG_TEXT, + ARG_SUBTITLE_ENCODING }; static void gst_play_base_bin_class_init (GstPlayBaseBinClass * klass); @@ -187,6 +188,12 @@ gst_play_base_bin_class_init (GstPlayBaseBinClass * klass) g_param_spec_int ("current-text", "Current text", "Currently playing text stream (-1 = none)", -1, G_MAXINT, -1, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_klass, ARG_SUBTITLE_ENCODING, + g_param_spec_string ("subtitle-encoding", "subtitle encoding", + "Encoding to assume if input subtitles are not in UTF-8 encoding. " + "If not set, the GST_SUBTITLE_ENCODING environment variable will " + "be checked for an encoding to use. If that is not set either, " + "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE)); GST_DEBUG_CATEGORY_INIT (gst_play_base_bin_debug, "playbasebin", 0, "playbasebin"); @@ -208,6 +215,8 @@ gst_play_base_bin_init (GstPlayBaseBin * play_base_bin) play_base_bin->source = NULL; play_base_bin->decoder = NULL; play_base_bin->subtitle = NULL; + play_base_bin->subencoding = NULL; + play_base_bin->subtitle_elements = NULL; play_base_bin->group_lock = g_mutex_new (); play_base_bin->group_cond = g_cond_new (); @@ -229,7 +238,12 @@ gst_play_base_bin_dispose (GObject * object) play_base_bin->uri = NULL; g_free (play_base_bin->suburi); play_base_bin->suburi = NULL; - + g_free (play_base_bin->subencoding); + play_base_bin->subencoding = NULL; + if (play_base_bin->subtitle_elements) { + g_slist_free (play_base_bin->subtitle_elements); + play_base_bin->subtitle_elements = NULL; + } G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -1147,6 +1161,48 @@ no_type: } } +static void +set_encoding_element (GstElement * element, gchar * encoding) +{ + GST_DEBUG_OBJECT (element, "setting encoding to %s", GST_STR_NULL (encoding)); + g_object_set (G_OBJECT (element), "subtitle-encoding", encoding, NULL); +} + + +static void +decodebin_element_added_cb (GstBin * decodebin, GstElement * element, + gpointer data) +{ + GstPlayBaseBin *play_base_bin = GST_PLAY_BASE_BIN (data); + gchar *encoding; + + if (!g_object_class_find_property (G_OBJECT_GET_CLASS (element), + "subtitle-encoding")) { + return; + } + + GST_OBJECT_LOCK (play_base_bin); + play_base_bin->subtitle_elements = + g_slist_append (play_base_bin->subtitle_elements, element); + encoding = g_strdup (play_base_bin->subencoding); + GST_OBJECT_UNLOCK (play_base_bin); + + set_encoding_element (element, encoding); + g_free (encoding); +} + +static void +decodebin_element_removed_cb (GstBin * decodebin, GstElement * element, + gpointer data) +{ + GstPlayBaseBin *play_base_bin = GST_PLAY_BASE_BIN (data); + + GST_OBJECT_LOCK (play_base_bin); + play_base_bin->subtitle_elements = + g_slist_remove (play_base_bin->subtitle_elements, element); + GST_OBJECT_UNLOCK (play_base_bin); +} + /* * Generate source ! subparse bins. @@ -1155,16 +1211,20 @@ no_type: static GstElement * setup_subtitle (GstPlayBaseBin * play_base_bin, gchar * sub_uri) { - GstElement *source, *subparse, *subbin; + GstElement *source, *subdecodebin, *subbin; source = gst_element_make_from_uri (GST_URI_SRC, sub_uri, NULL); if (!source) return NULL; - subparse = gst_element_factory_make ("decodebin", "subtitle-decoder"); - + subdecodebin = gst_element_factory_make ("decodebin", "subtitle-decoder"); + g_signal_connect (subdecodebin, "element-added", + G_CALLBACK (decodebin_element_added_cb), play_base_bin); + g_signal_connect (subdecodebin, "element-removed", + G_CALLBACK (decodebin_element_removed_cb), play_base_bin); subbin = gst_bin_new ("subtitle-bin"); - gst_bin_add_many (GST_BIN (subbin), source, subparse, NULL); - gst_element_link (source, subparse); + gst_bin_add_many (GST_BIN (subbin), source, subdecodebin, NULL); + + gst_element_link (source, subdecodebin); /* return the subtitle GstElement object */ return subbin; @@ -1437,6 +1497,11 @@ setup_source (GstPlayBaseBin * play_base_bin, gchar ** new_location) gst_element_factory_make ("decodebin", "decoder"))) goto no_decodebin; + g_signal_connect (play_base_bin->decoder, "element-added", + G_CALLBACK (decodebin_element_added_cb), play_base_bin); + g_signal_connect (play_base_bin->decoder, "element-removed", + G_CALLBACK (decodebin_element_removed_cb), play_base_bin); + gst_bin_add (GST_BIN (play_base_bin), play_base_bin->decoder); if (!gst_element_link (play_base_bin->source, play_base_bin->decoder)) @@ -1802,6 +1867,34 @@ gst_play_base_bin_set_property (GObject * object, guint prop_id, GST_STREAM_TYPE_TEXT, g_value_get_int (value)); GROUP_UNLOCK (play_base_bin); break; + case ARG_SUBTITLE_ENCODING: + { + const gchar *encoding; + GSList *list; + + encoding = g_value_get_string (value); + if (encoding && play_base_bin->subencoding && + !strcmp (play_base_bin->subencoding, encoding)) { + return; + } + if (encoding == NULL && play_base_bin->subencoding == NULL) + return; + + GST_OBJECT_LOCK (play_base_bin); + g_free (play_base_bin->subencoding); + play_base_bin->subencoding = g_strdup (encoding); + list = g_slist_copy (play_base_bin->subtitle_elements); + g_slist_foreach (list, (GFunc) gst_object_ref, NULL); + GST_OBJECT_UNLOCK (play_base_bin); + + /* we can't hold a lock when calling g_object_set() on a child, since + * the notify event will trigger GstObject to send a deep-notify event + * which will try to take the lock ... */ + g_slist_foreach (list, (GFunc) set_encoding_element, (gpointer) encoding); + g_slist_foreach (list, (GFunc) gst_object_unref, NULL); + g_slist_free (list); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1876,6 +1969,11 @@ gst_play_base_bin_get_property (GObject * object, guint prop_id, GValue * value, GST_STREAM_TYPE_TEXT)); GROUP_UNLOCK (play_base_bin); break; + case ARG_SUBTITLE_ENCODING: + GST_OBJECT_LOCK (play_base_bin); + g_value_set_string (value, play_base_bin->subencoding); + GST_OBJECT_UNLOCK (play_base_bin); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/playback/gstplaybasebin.h b/gst/playback/gstplaybasebin.h index 80e4007e8c..3826c98f0a 100644 --- a/gst/playback/gstplaybasebin.h +++ b/gst/playback/gstplaybasebin.h @@ -79,7 +79,9 @@ struct _GstPlayBaseBin { gboolean is_stream; GstElement *source; GstElement *decoder; - GstElement *subtitle; /* additional filesrc ! subparse bin */ + GstElement *subtitle; /* additional filesrc ! subparse bin */ + GSList *subtitle_elements; /* subtitle elements that have 'subtitle-encoding' property */ + gchar *subencoding; /* encoding to propagate to the above subtitle elements */ gboolean need_rebuild; /* group management - using own lock */ diff --git a/gst/subparse/gstsubparse.c b/gst/subparse/gstsubparse.c index f3782e2189..34222094fb 100644 --- a/gst/subparse/gstsubparse.c +++ b/gst/subparse/gstsubparse.c @@ -163,7 +163,7 @@ gst_sub_parse_class_init (GstSubParseClass * klass) element_class->change_state = gst_sub_parse_change_state; g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ENCODING, - g_param_spec_string ("encoding", "subtitle charset encoding", + g_param_spec_string ("subtitle-encoding", "subtitle charset encoding", "Encoding to assume if input subtitles are not in UTF-8 encoding. " "If not set, the GST_SUBTITLE_ENCODING environment variable will " "be checked for an encoding to use. If that is not set either, " @@ -278,6 +278,8 @@ gst_sub_parse_set_property (GObject * object, guint prop_id, case PROP_ENCODING: g_free (subparse->encoding); subparse->encoding = g_value_dup_string (value); + GST_LOG_OBJECT (object, "subtitle encoding set to %s", + GST_STR_NULL (subparse->encoding)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);