dnl *** pango ***
translit(dnm, m, l) AM_CONDITIONAL(USE_PANGO, true)
AG_GST_CHECK_FEATURE(PANGO, [Pango font rendering], pango, [
- AG_GST_PKG_CHECK_MODULES(PANGO, pango >= 1.16.0 pangocairo >= 1.16.0)
+ AG_GST_PKG_CHECK_MODULES(PANGO, pango >= 1.22.0 pangocairo >= 1.22.0)
])
dnl *** theora ***
fontmap = pango_cairo_font_map_get_default ();
klass->pango_context =
- pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
+ pango_font_map_create_context (PANGO_FONT_MAP (fontmap));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FONT_DESC,
g_param_spec_string ("font-desc", "font description",
"Pango font description of font "
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-static void
-gst_vorbis_dec_reset (GstVorbisDec * dec)
-{
- if (dec->taglist)
- gst_tag_list_free (dec->taglist);
- dec->taglist = NULL;
-}
-
static gboolean
vorbis_dec_start (GstAudioDecoder * dec)
{
vorbis_info_init (&vd->vi);
vorbis_comment_init (&vd->vc);
vd->initialized = FALSE;
- gst_vorbis_dec_reset (vd);
return TRUE;
}
vorbis_dsp_clear (&vd->vd);
vorbis_comment_clear (&vd->vc);
vorbis_info_clear (&vd->vi);
- gst_vorbis_dec_reset (vd);
return TRUE;
}
{
guint bitrate = 0;
gchar *encoder = NULL;
- GstTagList *list, *old_list;
+ GstTagList *list;
guint8 *data;
gsize size;
gst_tag_list_from_vorbiscomment (data, size, (guint8 *) "\003vorbis", 7,
&encoder);
- old_list = vd->taglist;
- vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE);
-
- if (old_list)
- gst_tag_list_free (old_list);
- gst_tag_list_free (list);
-
- if (!vd->taglist) {
+ if (!list) {
GST_ERROR_OBJECT (vd, "couldn't decode comments");
- vd->taglist = gst_tag_list_new_empty ();
+ list = gst_tag_list_new ();
}
+
if (encoder) {
if (encoder[0])
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
+ gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_ENCODER, encoder, NULL);
g_free (encoder);
}
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
+ gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_ENCODER_VERSION, vd->vi.version,
GST_TAG_AUDIO_CODEC, "Vorbis", NULL);
if (vd->vi.bitrate_nominal > 0 && vd->vi.bitrate_nominal <= 0x7FFFFFFF) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
+ gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
bitrate = vd->vi.bitrate_nominal;
}
if (vd->vi.bitrate_upper > 0 && vd->vi.bitrate_upper <= 0x7FFFFFFF) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
+ gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
if (!bitrate)
bitrate = vd->vi.bitrate_upper;
}
if (vd->vi.bitrate_lower > 0 && vd->vi.bitrate_lower <= 0x7FFFFFFF) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
+ gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
if (!bitrate)
bitrate = vd->vi.bitrate_lower;
}
if (bitrate) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
+ gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_BITRATE, (guint) bitrate, NULL);
}
+ gst_audio_decoder_merge_tags (GST_AUDIO_DECODER_CAST (vd), list,
+ GST_TAG_MERGE_REPLACE);
if (vd->initialized) {
- gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (vd),
- gst_event_new_tag (vd->taglist));
- vd->taglist = NULL;
+ gst_tag_list_free (list);
} else {
/* Only post them as messages for the time being. *
* They will be pushed on the pad once the decoder is initialized */
gst_element_post_message (GST_ELEMENT_CAST (vd),
- gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist)));
+ gst_message_new_tag (GST_OBJECT (vd), list));
}
return GST_FLOW_OK;
vd->initialized = TRUE;
- if (vd->taglist) {
- /* The tags have already been sent on the bus as messages. */
- gst_pad_push_event (GST_AUDIO_DECODER_SRC_PAD (vd),
- gst_event_new_tag (vd->taglist));
- vd->taglist = NULL;
- }
return GST_FLOW_OK;
/* ERRORS */
#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
vorbis_synthesis_restart (&vd->vd);
#endif
-
- if (hard)
- gst_vorbis_dec_reset (vd);
}
gboolean initialized;
GstAudioInfo info;
- GstTagList *taglist;
-
CopySampleFunc copy_samples;
};
g_assert (offset <= av);
if (offset) {
/* jumped a bit */
- GST_DEBUG_OBJECT (dec, "setting DISCONT");
+ GST_DEBUG_OBJECT (dec, "skipped %d; setting DISCONT", offset);
gst_adapter_flush (priv->adapter, offset);
flush = offset;
/* avoid parsing indefinitely */
return result;
}
+
+/**
+ * gst_audio_decoder_merge_tags:
+ * @dec: a #GstAudioDecoder
+ * @tags: a #GstTagList to merge
+ * @mode: the #GstTagMergeMode to use
+ *
+ * Adds tags to so-called pending tags, which will be processed
+ * before pushing out data downstream.
+ *
+ * Note that this is provided for convenience, and the subclass is
+ * not required to use this and can still do tag handling on its own,
+ * although it should be aware that baseclass already takes care
+ * of the usual CODEC/AUDIO_CODEC tags.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.37
+ */
+void
+gst_audio_decoder_merge_tags (GstAudioDecoder * dec,
+ const GstTagList * tags, GstTagMergeMode mode)
+{
+ GstTagList *otags;
+
+ g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
+ g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags));
+
+ GST_AUDIO_DECODER_STREAM_LOCK (dec);
+ if (tags)
+ GST_DEBUG_OBJECT (dec, "merging tags %" GST_PTR_FORMAT, tags);
+ otags = dec->priv->taglist;
+ dec->priv->taglist = gst_tag_list_merge (dec->priv->taglist, tags, mode);
+ if (otags)
+ gst_tag_list_free (otags);
+ GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
+}
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_DECODER))
#define GST_IS_AUDIO_DECODER_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_DECODER))
+#define GST_AUDIO_DECODER_CAST(obj) \
+ ((GstAudioDecoder *)(obj))
/**
* GST_AUDIO_DECODER_SINK_NAME:
gboolean gst_audio_decoder_get_needs_format (GstAudioDecoder * dec);
+void gst_audio_decoder_merge_tags (GstAudioDecoder * dec,
+ const GstTagList * tags, GstTagMergeMode mode);
+
G_END_DECLS
#endif /* _GST_AUDIO_DECODER_H_ */
/* We need to stop */
done = TRUE;
- GST_DEBUG ("Setting result to ERROR");
- dc->priv->current_info->result = GST_DISCOVERER_ERROR;
+ /* Don't override missing plugin result code for missing plugin errors */
+ if (dc->priv->current_info->result != GST_DISCOVERER_MISSING_PLUGINS ||
+ (!g_error_matches (gerr, GST_CORE_ERROR,
+ GST_CORE_ERROR_MISSING_PLUGIN) &&
+ !g_error_matches (gerr, GST_STREAM_ERROR,
+ GST_STREAM_ERROR_CODEC_NOT_FOUND))) {
+ GST_DEBUG ("Setting result to ERROR");
+ dc->priv->current_info->result = GST_DISCOVERER_ERROR;
+ }
}
break;
ret = (GstInstallPluginsReturn) WEXITSTATUS (status);
/* did the helper return an invalid status code? */
- if ((ret < 0 || ret >= GST_INSTALL_PLUGINS_STARTED_OK) &&
+ if (((guint) ret) >= GST_INSTALL_PLUGINS_STARTED_OK &&
ret != GST_INSTALL_PLUGINS_INTERNAL_FAILURE) {
ret = GST_INSTALL_PLUGINS_INVALID;
}
*/
gboolean
video_blend (GstBlendVideoFormatInfo * dest,
- GstBlendVideoFormatInfo * src, guint x, guint y)
+ GstBlendVideoFormatInfo * src, gint x, gint y)
{
guint i, j;
guint8 alpha;
gboolean video_blend (GstBlendVideoFormatInfo * dest,
GstBlendVideoFormatInfo * src,
- guint x, guint y);
+ gint x, gint y);
#endif
GstElement *elem;
GstPlayAudioChain *chain;
GstStateChangeReturn ret;
+ GstPlaySinkAudioConvert *conv;
chain = playsink->audiochain;
+ conv = GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv);
chain->chain.raw = raw;
}
g_object_set (chain->conv, "use-volume", FALSE, NULL);
- } else {
- GstPlaySinkAudioConvert *conv =
- GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv);
-
+ } else if (conv) {
/* no volume, we need to add a volume element when we can */
g_object_set (chain->conv, "use-volume",
! !(playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME), NULL);
gst_object_unref (overlay);
gst_message_unref (message);
gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (playsink));
+ } else {
+ GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin,
+ message);
}
break;
}
GstPlaySinkConvertBin * self)
{
gst_element_set_state (element, GST_STATE_NULL);
- gst_object_unref (GST_OBJECT_CAST (element));
+ gst_object_unref (element);
gst_bin_remove (GST_BIN_CAST (self), element);
}
#include "gst/glib-compat-private.h"
+/* for XkbKeycodeToKeysym */
+#include <X11/XKBlib.h>
+
GST_DEBUG_CATEGORY_EXTERN (gst_debug_ximagesink);
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
#define GST_CAT_DEFAULT gst_debug_ximagesink
KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask, &e)) {
KeySym keysym;
+ const char *key_str = NULL;
/* We lock only for the X function call */
g_mutex_unlock (ximagesink->x_lock);
case KeyRelease:
/* Key pressed/released over our window. We send upstream
events for interactivity/navigation */
- GST_DEBUG ("ximagesink key %d pressed over window at %d,%d",
- e.xkey.keycode, e.xkey.x, e.xkey.x);
g_mutex_lock (ximagesink->x_lock);
- keysym = XKeycodeToKeysym (ximagesink->xcontext->disp,
- e.xkey.keycode, 0);
- g_mutex_unlock (ximagesink->x_lock);
+ keysym = XkbKeycodeToKeysym (ximagesink->xcontext->disp,
+ e.xkey.keycode, 0, 0);
if (keysym != NoSymbol) {
- char *key_str = NULL;
-
- g_mutex_lock (ximagesink->x_lock);
key_str = XKeysymToString (keysym);
- g_mutex_unlock (ximagesink->x_lock);
- gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
- e.type == KeyPress ? "key-press" : "key-release", key_str);
} else {
- gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
- e.type == KeyPress ? "key-press" : "key-release", "unknown");
+ key_str = "unknown";
}
+ g_mutex_unlock (ximagesink->x_lock);
+ GST_DEBUG_OBJECT (ximagesink,
+ "key %d pressed over window at %d,%d (%s)",
+ e.xkey.keycode, e.xkey.x, e.xkey.y, key_str);
+ gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
+ e.type == KeyPress ? "key-press" : "key-release", key_str);
break;
default:
GST_DEBUG_OBJECT (ximagesink, "ximagesink unhandled X event (%d)",
#include "gst/glib-compat-private.h"
+/* for XkbKeycodeToKeysym */
+#include <X11/XKBlib.h>
+
GST_DEBUG_CATEGORY_EXTERN (gst_debug_xvimagesink);
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
#define GST_CAT_DEFAULT gst_debug_xvimagesink
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask,
&e)) {
KeySym keysym;
+ const char *key_str = NULL;
/* We lock only for the X function call */
g_mutex_unlock (xvimagesink->x_lock);
case KeyRelease:
/* Key pressed/released over our window. We send upstream
events for interactivity/navigation */
- GST_DEBUG ("xvimagesink key %d pressed over window at %d,%d",
- e.xkey.keycode, e.xkey.x, e.xkey.y);
g_mutex_lock (xvimagesink->x_lock);
- keysym = XKeycodeToKeysym (xvimagesink->xcontext->disp,
- e.xkey.keycode, 0);
- g_mutex_unlock (xvimagesink->x_lock);
+ keysym = XkbKeycodeToKeysym (xvimagesink->xcontext->disp,
+ e.xkey.keycode, 0, 0);
if (keysym != NoSymbol) {
- char *key_str = NULL;
-
- g_mutex_lock (xvimagesink->x_lock);
key_str = XKeysymToString (keysym);
- g_mutex_unlock (xvimagesink->x_lock);
- gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink),
- e.type == KeyPress ? "key-press" : "key-release", key_str);
} else {
- gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink),
- e.type == KeyPress ? "key-press" : "key-release", "unknown");
+ key_str = "unknown";
}
+ g_mutex_unlock (xvimagesink->x_lock);
+ GST_DEBUG_OBJECT (xvimagesink,
+ "key %d pressed over window at %d,%d (%s)",
+ e.xkey.keycode, e.xkey.x, e.xkey.y, key_str);
+ gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink),
+ e.type == KeyPress ? "key-press" : "key-release", key_str);
break;
default:
GST_DEBUG_OBJECT (xvimagesink, "xvimagesink unhandled X event (%d)",
xcontext->adaptors[i] = g_strdup (adaptors[i].name);
}
- if (xvimagesink->adaptor_no >= 0 &&
+ if (xvimagesink->adaptor_no != -1 &&
xvimagesink->adaptor_no < xcontext->nb_adaptors) {
/* Find xv port from user defined adaptor */
gst_lookup_xv_port_from_adaptor (xcontext, adaptors,
tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_0);
tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_1);
tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_2);
- tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_3);
+ tcase_skip_broken_test (tc_chain, test_downscale_640x480_1x240_method_3);
tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_0);
tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_1);
tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_2);
GST_END_TEST;
+GST_START_TEST (test_disco_missing_plugins)
+{
+ const gchar *files[] = { "test.mkv", "test.mp3", "partialframe.mjpeg" };
+ GError *err = NULL;
+ GstDiscoverer *dc;
+ GstDiscovererInfo *info;
+ GstDiscovererResult result;
+ gchar *uri, *path;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (files); ++i) {
+ dc = gst_discoverer_new (5 * GST_SECOND, &err);
+ fail_unless (dc != NULL);
+ fail_unless (err == NULL);
+
+ /* GST_TEST_FILE comes from makefile CFLAGS */
+ path = g_build_filename (GST_TEST_FILES_PATH, files[i], NULL);
+ uri = gst_filename_to_uri (path, &err);
+ g_free (path);
+ fail_unless (err == NULL);
+
+ GST_INFO ("discovering uri '%s'", uri);
+ info = gst_discoverer_discover_uri (dc, uri, &err);
+ fail_unless (info != NULL);
+ fail_unless (err != NULL);
+ result = gst_discoverer_info_get_result (info);
+ GST_INFO ("result: %d, error message: %s", result, err->message);
+ fail_unless_equals_int (result, GST_DISCOVERER_MISSING_PLUGINS);
+ GST_INFO ("misc: %" GST_PTR_FORMAT, gst_discoverer_info_get_misc (info));
+
+ gst_discoverer_info_unref (info);
+ g_error_free (err);
+ err = NULL;
+ g_free (uri);
+ g_object_unref (dc);
+ }
+}
+
+GST_END_TEST;
+
static Suite *
discoverer_suite (void)
{
tcase_add_test (tc_chain, test_disco_sync_reuse_ogg);
tcase_add_test (tc_chain, test_disco_sync_reuse_mp3);
tcase_add_test (tc_chain, test_disco_sync_reuse_timeout);
+ tcase_add_test (tc_chain, test_disco_missing_plugins);
return s;
}
hls.m3u8 \
license-uris \
partialframe.mjpeg \
+ test.mkv \
test.mp3 \
theora-vorbis.ogg
gst_audio_decoder_get_plc_aware
gst_audio_decoder_get_tolerance
gst_audio_decoder_get_type
+ gst_audio_decoder_merge_tags
gst_audio_decoder_set_byte_time
gst_audio_decoder_set_drainable
gst_audio_decoder_set_latency