From 185a8ddcaa0caff36e5eb801a3347e1c849061df Mon Sep 17 00:00:00 2001 From: Blaise Gassend Date: Tue, 15 Mar 2011 19:47:11 +0100 Subject: [PATCH 01/34] alsamixer: Store return values of poll functions in a signed integer Negative return values are used for errors and storing them in an unsigned integer will make it impossible to detect the errors. Fixes bug #644845. --- ext/alsa/gstalsamixer.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/alsa/gstalsamixer.c b/ext/alsa/gstalsamixer.c index 13eba89120..b30a7bba79 100644 --- a/ext/alsa/gstalsamixer.c +++ b/ext/alsa/gstalsamixer.c @@ -416,7 +416,7 @@ static void task_monitor_alsa (gpointer data) { struct pollfd *pfds; - unsigned int nfds, rnfds; + int nfds, rnfds; unsigned short revents; GstAlsaMixer *mixer = (GstAlsaMixer *) data; gint ret; @@ -733,7 +733,7 @@ gst_alsa_mixer_set_mute (GstAlsaMixer * mixer, GstMixerTrack * track, gst_alsa_mixer_track_update (alsa_track); - if (!!(mute) == !!(track->flags & GST_MIXER_TRACK_MUTE)) { + if (! !(mute) == ! !(track->flags & GST_MIXER_TRACK_MUTE)) { g_static_rec_mutex_unlock (mixer->rec_mutex); return; } @@ -785,7 +785,7 @@ gst_alsa_mixer_set_record (GstAlsaMixer * mixer, gst_alsa_mixer_track_update (alsa_track); - if (!!(record) == !!(track->flags & GST_MIXER_TRACK_RECORD)) { + if (! !(record) == ! !(track->flags & GST_MIXER_TRACK_RECORD)) { g_static_rec_mutex_unlock (mixer->rec_mutex); return; } @@ -917,8 +917,8 @@ gst_alsa_mixer_update_track (GstAlsaMixer * mixer, return; } - old_mute = !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE)); - old_record = !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)); + old_mute = ! !(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE)); + old_record = ! !(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)); old_volumes = g_new (gint, track->num_channels); n_channels = track->num_channels; memcpy (old_volumes, alsa_track->volumes, @@ -927,13 +927,13 @@ gst_alsa_mixer_update_track (GstAlsaMixer * mixer, gst_alsa_mixer_track_update (alsa_track); if (old_record != - !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD))) { + ! !(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD))) { gst_mixer_record_toggled (mixer->interface, track, - !!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)); + ! !GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)); } - if (old_mute != !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE))) { + if (old_mute != ! !(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE))) { gst_mixer_mute_toggled (mixer->interface, track, - !!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE)); + ! !GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE)); } n_channels = MIN (n_channels, track->num_channels); From e8f5b3a579aa31ccbcb33a8920004fe8d9bbdeca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 16 Mar 2011 10:19:42 +0000 Subject: [PATCH 02/34] uridecodebin: post proper error message if decodebin2/typefind elements are missing Post better error messages in case typefind/decodebin2 are missing or could not be loaded for some reason (e.g. because they inadvertently got blacklisted). https://bugzilla.gnome.org/show_bug.cgi?id=644892 --- gst/playback/gsturidecodebin.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/gst/playback/gsturidecodebin.c b/gst/playback/gsturidecodebin.c index f4551e3b4f..bf1058349f 100644 --- a/gst/playback/gsturidecodebin.c +++ b/gst/playback/gsturidecodebin.c @@ -1539,6 +1539,11 @@ make_decoder (GstURIDecodeBin * decoder) if (!decodebin) goto no_decodebin; + + /* sanity check */ + if (decodebin->numsinkpads == 0) + goto no_typefind; + /* connect signals to proxy */ g_signal_connect (decodebin, "unknown-type", G_CALLBACK (proxy_unknown_type_signal), decoder); @@ -1609,6 +1614,15 @@ make_decoder (GstURIDecodeBin * decoder) no_decodebin: { post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "decodebin2"); + GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (NULL), + ("No decodebin2 element, check your installation")); + return NULL; + } +no_typefind: + { + gst_object_unref (decodebin); + GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (NULL), + ("No typefind element, decodebin2 is unusable, check your installation")); return NULL; } } @@ -1762,6 +1776,8 @@ setup_streaming (GstURIDecodeBin * decoder) no_typefind: { post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "typefind"); + GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (NULL), + ("No typefind element, check your installation")); return FALSE; } could_not_link: From 83679ef8f88e8e81511c9ecd1cbb7c8f60115bb2 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Mon, 7 Feb 2011 09:13:39 +0200 Subject: [PATCH 03/34] check: Really fix the linking order of libs/tag Follow-up to commit 5f5c52c, which only fixed the CFLAGS order. Fix the linker order as well. --- tests/check/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index ee9981916f..c5bd554623 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -290,8 +290,8 @@ libs_tag_CFLAGS = \ $(GST_BASE_CFLAGS) \ $(AM_CFLAGS) libs_tag_LDADD = \ - $(GST_BASE_LIBS) \ - $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la $(LDADD) + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(LDADD) libs_pbutils_CFLAGS = \ $(GST_PLUGINS_BASE_CFLAGS) \ From 093a91eec8ff690ed8aa4ae09f1ee290f7ea9d03 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 16 Mar 2011 15:38:31 +0200 Subject: [PATCH 04/34] textoverlay: Clean up alignment docs a bit and remove horiz top alignment enum --- ext/pango/gsttextoverlay.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/pango/gsttextoverlay.h b/ext/pango/gsttextoverlay.h index d230121c43..5cd42601d4 100644 --- a/ext/pango/gsttextoverlay.h +++ b/ext/pango/gsttextoverlay.h @@ -27,7 +27,9 @@ typedef struct _GstTextOverlayClass GstTextOverlayClass; * GstTextOverlayVAlign: * @GST_TEXT_OVERLAY_VALIGN_BASELINE: draw text on the baseline * @GST_TEXT_OVERLAY_VALIGN_BOTTOM: draw text on the bottom - * @GST_TEXT_OVERLAY_VALIGN_TOP: draw test on top + * @GST_TEXT_OVERLAY_VALIGN_TOP: draw text on top + * @GST_TEXT_OVERLAY_VALIGN_POS: draw text according to the #GstTextOverlay:ypos property + * @GST_TEXT_OVERLAY_VALIGN_CENTER: draw text vertically centered * * Vertical alignment of the text. */ @@ -44,14 +46,16 @@ typedef enum { * @GST_TEXT_OVERLAY_HALIGN_LEFT: align text left * @GST_TEXT_OVERLAY_HALIGN_CENTER: align text center * @GST_TEXT_OVERLAY_HALIGN_RIGHT: align text right + * @GST_TEXT_OVERLAY_HALIGN_POS: position text according to the #GstTextOverlay:xpos property * * Horizontal alignment of the text. */ +/* FIXME 0.11: remove GST_TEXT_OVERLAY_HALIGN_UNUSED */ typedef enum { GST_TEXT_OVERLAY_HALIGN_LEFT, GST_TEXT_OVERLAY_HALIGN_CENTER, GST_TEXT_OVERLAY_HALIGN_RIGHT, - GST_TEXT_OVERLAY_HALIGN_TOP, + GST_TEXT_OVERLAY_HALIGN_UNUSED, GST_TEXT_OVERLAY_HALIGN_POS } GstTextOverlayHAlign; From 103fb67d20cdd7c3889db23287ae53130b329498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 17 Mar 2011 21:50:15 -0400 Subject: [PATCH 05/34] rtpbuffer: Off-by-one error when creating RTP header extensions with a two-byte header --- gst-libs/gst/rtp/gstrtpbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-libs/gst/rtp/gstrtpbuffer.c b/gst-libs/gst/rtp/gstrtpbuffer.c index 8f94d3f5d4..149a9669ec 100644 --- a/gst-libs/gst/rtp/gstrtpbuffer.c +++ b/gst-libs/gst/rtp/gstrtpbuffer.c @@ -1782,7 +1782,7 @@ gst_rtp_buffer_add_extension_twobytes_header (GstBuffer * buffer, gst_rtp_buffer_set_extension_data (buffer, (0x100 << 4) | (appbits & 0x0F), wordlen); } else { - wordlen = (size + 1) / 4 + (((size + 1) % 4) ? 1 : 0); + wordlen = (size + 2) / 4 + (((size + 2) % 4) ? 1 : 0); gst_rtp_buffer_set_extension_data (buffer, (0x100 << 4) | (appbits & 0x0F), wordlen); From 75897c716fb4ff60febd1aaeae9752edf35463cd Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 21 Mar 2011 18:33:03 -0300 Subject: [PATCH 06/34] tag: xmp: Add missing schema creation tiff schema entries were being added to the previous schema (xap) because a new one wasn't being created for it. --- gst-libs/gst/tag/gstxmptag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c index c3bc6360e8..0b1b7bd29d 100644 --- a/gst-libs/gst/tag/gstxmptag.c +++ b/gst-libs/gst/tag/gstxmptag.c @@ -205,7 +205,6 @@ _xmp_tag_get_mapping (const gchar * gst_tag) ret = (GPtrArray *) gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key)); } - return ret; } @@ -822,6 +821,7 @@ _init_xmp_tag_map () _gst_xmp_add_schema ("xmp", schema); /* tiff */ + schema = gst_xmp_schema_new (); _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DEVICE_MANUFACTURER, "tiff:Make", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); From 0af549ace012db3a8fb18a099a6fa4198257857d Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Mon, 21 Mar 2011 19:22:30 +0100 Subject: [PATCH 07/34] encoding-profile: Fix syntax in Example: Creating a profile https://bugzilla.gnome.org/show_bug.cgi?id=645437 --- gst-libs/gst/pbutils/encoding-profile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/pbutils/encoding-profile.c b/gst-libs/gst/pbutils/encoding-profile.c index b1c8051b6e..eaa7507cba 100644 --- a/gst-libs/gst/pbutils/encoding-profile.c +++ b/gst-libs/gst/pbutils/encoding-profile.c @@ -68,12 +68,12 @@ * gst_caps_unref (caps); * * caps = gst_caps_from_string("video/x-theora"); - * sprof = gst_encoding_container_profile_add_profile( + * gst_encoding_container_profile_add_profile(prof, * (GstEncodingProfile*) gst_encoding_video_profile_new(caps, NULL, NULL, 0)); * gst_caps_unref (caps); * * caps = gst_caps_from_string("audio/x-vorbis"); - * sprof = gst_encoding_container_profile_add_profile( + * gst_encoding_container_profile_add_profile(prof, * (GstEncodingProfile*) gst_encoding_audio_profile_new(caps, NULL, NULL, 0)); * gst_caps_unref (caps); * From 29952f7d7fa5ca8a4d12a2bc5fd5d81573d885bc Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Fri, 18 Mar 2011 19:34:57 +0100 Subject: [PATCH 08/34] autogen: wingo signed comment --- autogen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autogen.sh b/autogen.sh index 70c5340a1d..820a017fbb 100755 --- a/autogen.sh +++ b/autogen.sh @@ -80,7 +80,7 @@ tool_run "$libtoolize" "--copy --force" tool_run "$aclocal" "-I m4 -I common/m4 $ACLOCAL_FLAGS" tool_run "$autoheader" -# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode -- wingo +# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode echo timestamp > stamp-h.in 2> /dev/null tool_run "$autoconf" From b41cca7f40bf6eac470d516c57d39fa2a5c65845 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Tue, 22 Mar 2011 12:44:49 +0100 Subject: [PATCH 09/34] configure.ac: redundant use of AC_MSG_RESULT() cleaned the redundant use of AC_MSG_RESULT() in configure.ac --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index c8d8597750..b91b4f485f 100644 --- a/configure.ac +++ b/configure.ac @@ -731,7 +731,6 @@ AG_GST_CHECK_FEATURE(GIO, [GIO library], gio, [ [The GIO library directory.]) ], [ HAVE_GIO="no" - AC_MSG_RESULT(no) ]) AC_SUBST(GIO_CFLAGS) AC_SUBST(GIO_LIBS) From 91ed9290b880804ac479a9ddcab256494f7a31d6 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 24 Feb 2011 08:42:34 -0300 Subject: [PATCH 10/34] videoscale: Fix assertion on caps fixation When fixating caps, from_par should always be initialized with a fixed value. In case the fixation is from src to sink pad it was setting the from par (srcpad par) to a fraction range, this patch initializes it to 1/1, based on the assumption that missing PAR is 1/1. https://bugzilla.gnome.org/show_bug.cgi?id=641952 --- gst/videoscale/gstvideoscale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/videoscale/gstvideoscale.c b/gst/videoscale/gstvideoscale.c index aaf104bd42..ac2968a5b0 100644 --- a/gst/videoscale/gstvideoscale.c +++ b/gst/videoscale/gstvideoscale.c @@ -501,8 +501,8 @@ gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction, NULL); } if (!from_par) { - g_value_init (&fpar, GST_TYPE_FRACTION_RANGE); - gst_value_set_fraction_range_full (&fpar, 1, G_MAXINT, G_MAXINT, 1); + g_value_init (&fpar, GST_TYPE_FRACTION); + gst_value_set_fraction (&fpar, 1, 1); from_par = &fpar; } } From a08227505f2cfa912056b397f37fd656b28e5508 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Tue, 22 Mar 2011 11:59:40 -0700 Subject: [PATCH 11/34] video: Add gst_video_format_new_template_caps() --- gst-libs/gst/video/video.c | 150 ++++++++++++++++++++++++------------- gst-libs/gst/video/video.h | 3 +- 2 files changed, 102 insertions(+), 51 deletions(-) diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c index d9569a4e8c..83330c0224 100644 --- a/gst-libs/gst/video/video.c +++ b/gst-libs/gst/video/video.c @@ -544,36 +544,14 @@ gst_video_format_new_caps_interlaced (GstVideoFormat format, return res; } -/** - * gst_video_format_new_caps: - * @format: the #GstVideoFormat describing the raw video format - * @width: width of video - * @height: height of video - * @framerate_n: numerator of frame rate - * @framerate_d: denominator of frame rate - * @par_n: numerator of pixel aspect ratio - * @par_d: denominator of pixel aspect ratio - * - * Creates a new #GstCaps object based on the parameters provided. - * - * Since: 0.10.16 - * - * Returns: a new #GstCaps object, or NULL if there was an error - */ -GstCaps * -gst_video_format_new_caps (GstVideoFormat format, int width, - int height, int framerate_n, int framerate_d, int par_n, int par_d) +static GstCaps * +gst_video_format_new_caps_raw (GstVideoFormat format) { g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); - g_return_val_if_fail (width > 0 && height > 0, NULL); if (gst_video_format_is_yuv (format)) { return gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format), - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL); + "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format), NULL); } if (gst_video_format_is_rgb (format)) { GstCaps *caps; @@ -651,14 +629,11 @@ gst_video_format_new_caps (GstVideoFormat format, int width, mask = 0xff0000; } red_mask = - mask >> (8 * gst_video_format_get_component_offset (format, 0, - width, height)); + mask >> (8 * gst_video_format_get_component_offset (format, 0, 0, 0)); green_mask = - mask >> (8 * gst_video_format_get_component_offset (format, 1, - width, height)); + mask >> (8 * gst_video_format_get_component_offset (format, 1, 0, 0)); blue_mask = - mask >> (8 * gst_video_format_get_component_offset (format, 2, - width, height)); + mask >> (8 * gst_video_format_get_component_offset (format, 2, 0, 0)); } else if (bpp == 16) { switch (format) { case GST_VIDEO_FORMAT_RGB16: @@ -690,12 +665,7 @@ gst_video_format_new_caps (GstVideoFormat format, int width, } caps = gst_caps_new_simple ("video/x-raw-rgb", - "bpp", G_TYPE_INT, bpp, - "depth", G_TYPE_INT, depth, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL); + "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL); if (bpp != 8) { gst_caps_set_simple (caps, @@ -707,8 +677,7 @@ gst_video_format_new_caps (GstVideoFormat format, int width, if (have_alpha) { alpha_mask = - mask >> (8 * gst_video_format_get_component_offset (format, 3, - width, height)); + mask >> (8 * gst_video_format_get_component_offset (format, 3, 0, 0)); gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, alpha_mask, NULL); } return caps; @@ -740,21 +709,12 @@ gst_video_format_new_caps (GstVideoFormat format, int width, if (bpp > 8) { caps = gst_caps_new_simple ("video/x-raw-gray", - "bpp", G_TYPE_INT, bpp, - "depth", G_TYPE_INT, depth, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL); + "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL); } else { caps = gst_caps_new_simple ("video/x-raw-gray", "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, - "endianness", G_TYPE_INT, G_BIG_ENDIAN, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL); + "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL); } return caps; @@ -763,6 +723,96 @@ gst_video_format_new_caps (GstVideoFormat format, int width, return NULL; } +/** + * gst_video_format_new_template_caps: + * @format: the #GstVideoFormat describing the raw video format + * + * Creates a new #GstCaps object based on the parameters provided. + * Size, frame rate, and pixel aspect ratio are set to the full + * range. + * + * Since: 0.10.33 + * + * Returns: a new #GstCaps object, or NULL if there was an error + */ +GstCaps * +gst_video_format_new_template_caps (GstVideoFormat format) +{ + GstCaps *caps; + GstStructure *structure; + + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); + + caps = gst_video_format_new_caps_raw (format); + if (caps) { + GValue value = { 0 }; + GValue v = { 0 }; + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_set (structure, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, + "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + + g_value_init (&value, GST_TYPE_LIST); + g_value_init (&v, G_TYPE_BOOLEAN); + g_value_set_boolean (&v, TRUE); + gst_value_list_append_value (&value, &v); + g_value_set_boolean (&v, FALSE); + gst_value_list_append_value (&value, &v); + + gst_structure_set_value (structure, "interlaced", &value); + + g_value_reset (&value); + g_value_reset (&v); + } + + return caps; +} + +/** + * gst_video_format_new_caps: + * @format: the #GstVideoFormat describing the raw video format + * @width: width of video + * @height: height of video + * @framerate_n: numerator of frame rate + * @framerate_d: denominator of frame rate + * @par_n: numerator of pixel aspect ratio + * @par_d: denominator of pixel aspect ratio + * + * Creates a new #GstCaps object based on the parameters provided. + * + * Since: 0.10.16 + * + * Returns: a new #GstCaps object, or NULL if there was an error + */ +GstCaps * +gst_video_format_new_caps (GstVideoFormat format, int width, + int height, int framerate_n, int framerate_d, int par_n, int par_d) +{ + GstCaps *caps; + GstStructure *structure; + + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); + g_return_val_if_fail (width > 0 && height > 0, NULL); + + caps = gst_video_format_new_caps_raw (format); + if (caps) { + structure = gst_caps_get_structure (caps, 0); + + gst_structure_set (structure, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL); + } + + return caps; +} + + /** * gst_video_format_from_fourcc: * @fourcc: a FOURCC value representing raw YUV video diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h index 969cb05072..8f5cabfb76 100644 --- a/gst-libs/gst/video/video.h +++ b/gst-libs/gst/video/video.h @@ -461,7 +461,8 @@ GstCaps * gst_video_format_new_caps (GstVideoFormat format, int par_n, int par_d); GstCaps * gst_video_format_new_caps_interlaced (GstVideoFormat format, int width, int height, int framerate_n, int framerate_d, - int par_n, int par_d, gboolean interlaced); + int par_n, int par_d, gboolean interlaced); +GstCaps * gst_video_format_new_template_caps (GstVideoFormat format); GstVideoFormat gst_video_format_from_fourcc (guint32 fourcc); guint32 gst_video_format_to_fourcc (GstVideoFormat format); gboolean gst_video_format_is_rgb (GstVideoFormat format); From 4e49d589172b7e87bbc443c8d692ebb1783b71d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 17 Mar 2011 13:47:10 +0100 Subject: [PATCH 12/34] playbin2: Only consider the audio/video sinks in autoplug_continue for the normal uridecodebin Considering them for the subtitle uridecodebin will add audio/video streams that might be in a file used as subtitle file. --- gst/playback/gstplaybin2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index 8d6dbccede..a2082ba16d 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -2972,9 +2972,17 @@ autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps, ret = !gst_caps_can_intersect (caps, subcaps); gst_caps_unref (subcaps); } + /* If autoplugging can stop don't do additional checks */ if (!ret) goto done; + /* If this is from the subtitle uridecodebin we don't need to + * check the audio and video sink */ + if (group->suburidecodebin + && gst_object_has_ancestor (GST_OBJECT_CAST (element), + GST_OBJECT_CAST (group->suburidecodebin))) + goto done; + if ((sink = group->playbin->audio_sink)) { sinkpad = gst_element_get_static_pad (sink, "sink"); if (sinkpad) { From a0ff13217a1da3693533a4ca7854ed28a71701f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 16 Mar 2011 15:56:34 +0100 Subject: [PATCH 13/34] playbin2: Always prefer the custom set sink and also set it back to NULL in all cases. --- gst/playback/gstplaybin2.c | 129 +++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 34 deletions(-) diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index a2082ba16d..2bf07dec74 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -1139,11 +1139,17 @@ free_group (GstPlayBin * playbin, GstSourceGroup * group) g_ptr_array_free (group->text_channels, TRUE); g_mutex_free (group->lock); - if (group->audio_sink) + if (group->audio_sink) { + if (group->audio_sink != playbin->audio_sink) + gst_element_set_state (group->audio_sink, GST_STATE_NULL); gst_object_unref (group->audio_sink); + } group->audio_sink = NULL; - if (group->video_sink) + if (group->video_sink) { + if (group->video_sink != playbin->video_sink) + gst_element_set_state (group->video_sink, GST_STATE_NULL); gst_object_unref (group->video_sink); + } group->video_sink = NULL; g_list_free (group->stream_changed_pending); @@ -1239,12 +1245,18 @@ gst_play_bin_finalize (GObject * object) if (playbin->source) gst_object_unref (playbin->source); - if (playbin->video_sink) + if (playbin->video_sink) { + gst_element_set_state (playbin->video_sink, GST_STATE_NULL); gst_object_unref (playbin->video_sink); - if (playbin->audio_sink) + } + if (playbin->audio_sink) { + gst_element_set_state (playbin->audio_sink, GST_STATE_NULL); gst_object_unref (playbin->audio_sink); - if (playbin->text_sink) + } + if (playbin->text_sink) { + gst_element_set_state (playbin->text_sink, GST_STATE_NULL); gst_object_unref (playbin->text_sink); + } if (playbin->elements) gst_plugin_feature_list_free (playbin->elements); @@ -2756,30 +2768,22 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group) if (configure) { /* if we have custom sinks, configure them now */ GST_SOURCE_GROUP_LOCK (group); - if (group->audio_sink) { - GST_INFO_OBJECT (playbin, "setting custom audio sink %" GST_PTR_FORMAT, - group->audio_sink); - gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO, - group->audio_sink); - } else { - GST_INFO_OBJECT (playbin, "setting default audio sink %" GST_PTR_FORMAT, - playbin->audio_sink); - gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO, - playbin->audio_sink); - } - if (group->video_sink) { - GST_INFO_OBJECT (playbin, "setting custom video sink %" GST_PTR_FORMAT, - group->video_sink); - gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO, - group->video_sink); - } else { - GST_INFO_OBJECT (playbin, "setting default video sink %" GST_PTR_FORMAT, - playbin->video_sink); - gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO, - playbin->video_sink); - } + + GST_INFO_OBJECT (playbin, "setting custom audio sink %" GST_PTR_FORMAT, + group->audio_sink); + gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO, + group->audio_sink); + + GST_INFO_OBJECT (playbin, "setting custom video sink %" GST_PTR_FORMAT, + group->video_sink); + gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO, + group->video_sink); + + GST_INFO_OBJECT (playbin, "setting custom text sink %" GST_PTR_FORMAT, + playbin->text_sink); gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_TEXT, playbin->text_sink); + GST_SOURCE_GROUP_UNLOCK (group); GST_LOG_OBJECT (playbin, "reconfigure sink"); @@ -2961,8 +2965,9 @@ autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps, if ((sink = group->playbin->text_sink)) sinkpad = gst_element_get_static_pad (sink, "sink"); if (sinkpad) { - GstCaps *sinkcaps = gst_pad_get_caps_reffed (sinkpad); + GstCaps *sinkcaps; + sinkcaps = gst_pad_get_caps_reffed (sinkpad); if (!gst_caps_is_any (sinkcaps)) ret = !gst_pad_accept_caps (sinkpad, caps); gst_caps_unref (sinkcaps); @@ -2983,11 +2988,12 @@ autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps, GST_OBJECT_CAST (group->suburidecodebin))) goto done; - if ((sink = group->playbin->audio_sink)) { + if ((sink = group->audio_sink)) { sinkpad = gst_element_get_static_pad (sink, "sink"); if (sinkpad) { - GstCaps *sinkcaps = gst_pad_get_caps_reffed (sinkpad); + GstCaps *sinkcaps; + sinkcaps = gst_pad_get_caps_reffed (sinkpad); if (!gst_caps_is_any (sinkcaps)) ret = !gst_pad_accept_caps (sinkpad, caps); gst_caps_unref (sinkcaps); @@ -2997,11 +3003,12 @@ autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps, if (!ret) goto done; - if ((sink = group->playbin->video_sink)) { + if ((sink = group->video_sink)) { sinkpad = gst_element_get_static_pad (sink, "sink"); if (sinkpad) { - GstCaps *sinkcaps = gst_pad_get_caps_reffed (sinkpad); + GstCaps *sinkcaps; + sinkcaps = gst_pad_get_caps_reffed (sinkpad); if (!gst_caps_is_any (sinkcaps)) ret = !gst_pad_accept_caps (sinkpad, caps); gst_caps_unref (sinkcaps); @@ -3183,6 +3190,12 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target) GST_SOURCE_GROUP_LOCK (group); + /* First set up the custom sources */ + if (playbin->audio_sink) + group->audio_sink = gst_object_ref (playbin->audio_sink); + if (playbin->video_sink) + group->video_sink = gst_object_ref (playbin->video_sink); + g_list_free (group->stream_changed_pending); group->stream_changed_pending = NULL; if (!group->stream_changed_pending_lock) @@ -3334,6 +3347,22 @@ no_decodebin: { GstMessage *msg; + /* delete any custom sinks we might have */ + if (group->audio_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->audio_sink != playbin->audio_sink) + gst_element_set_state (group->audio_sink, GST_STATE_NULL); + gst_object_unref (group->audio_sink); + } + group->audio_sink = NULL; + if (group->video_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->video_sink != playbin->video_sink) + gst_element_set_state (group->video_sink, GST_STATE_NULL); + gst_object_unref (group->video_sink); + } + group->video_sink = NULL; + GST_SOURCE_GROUP_UNLOCK (group); msg = gst_missing_element_message_new (GST_ELEMENT_CAST (playbin), @@ -3346,6 +3375,22 @@ no_decodebin: } uridecodebin_failure: { + /* delete any custom sinks we might have */ + if (group->audio_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->audio_sink != playbin->audio_sink) + gst_element_set_state (group->audio_sink, GST_STATE_NULL); + gst_object_unref (group->audio_sink); + } + group->audio_sink = NULL; + if (group->video_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->video_sink != playbin->video_sink) + gst_element_set_state (group->video_sink, GST_STATE_NULL); + gst_object_unref (group->video_sink); + } + group->video_sink = NULL; + GST_DEBUG_OBJECT (playbin, "failed state change of uridecodebin"); return FALSE; } @@ -3403,11 +3448,19 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group) } } /* delete any custom sinks we might have */ - if (group->audio_sink) + if (group->audio_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->audio_sink != playbin->audio_sink) + gst_element_set_state (group->audio_sink, GST_STATE_NULL); gst_object_unref (group->audio_sink); + } group->audio_sink = NULL; - if (group->video_sink) + if (group->video_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->video_sink != playbin->video_sink) + gst_element_set_state (group->video_sink, GST_STATE_NULL); gst_object_unref (group->video_sink); + } group->video_sink = NULL; if (group->uridecodebin) { @@ -3623,6 +3676,14 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition) } } + /* Set our sinks back to NULL, they might not be child of playbin */ + if (playbin->audio_sink) + gst_element_set_state (playbin->audio_sink, GST_STATE_NULL); + if (playbin->video_sink) + gst_element_set_state (playbin->video_sink, GST_STATE_NULL); + if (playbin->text_sink) + gst_element_set_state (playbin->text_sink, GST_STATE_NULL); + /* make sure the groups don't perform a state change anymore until we * enable them again */ groups_set_locked_state (playbin, TRUE); From b76efc7f5dcefb43b1ee737fdb5a4511826122c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 16 Mar 2011 15:56:34 +0100 Subject: [PATCH 14/34] playbin2: Set sinks to READY before checking if it accept caps Fixes bug #642732. --- gst/playback/gstplaybin2.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index 2bf07dec74..1cd9d5b489 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -2967,6 +2967,12 @@ autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps, if (sinkpad) { GstCaps *sinkcaps; + /* Ignore errors here, if a custom sink fails to go + * to READY things are wrong and will error out later + */ + if (GST_STATE (sink) < GST_STATE_READY) + gst_element_set_state (sink, GST_STATE_READY); + sinkcaps = gst_pad_get_caps_reffed (sinkpad); if (!gst_caps_is_any (sinkcaps)) ret = !gst_pad_accept_caps (sinkpad, caps); @@ -2993,6 +2999,12 @@ autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps, if (sinkpad) { GstCaps *sinkcaps; + /* Ignore errors here, if a custom sink fails to go + * to READY things are wrong and will error out later + */ + if (GST_STATE (sink) < GST_STATE_READY) + gst_element_set_state (sink, GST_STATE_READY); + sinkcaps = gst_pad_get_caps_reffed (sinkpad); if (!gst_caps_is_any (sinkcaps)) ret = !gst_pad_accept_caps (sinkpad, caps); @@ -3008,6 +3020,12 @@ autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps, if (sinkpad) { GstCaps *sinkcaps; + /* Ignore errors here, if a custom sink fails to go + * to READY things are wrong and will error out later + */ + if (GST_STATE (sink) < GST_STATE_READY) + gst_element_set_state (sink, GST_STATE_READY); + sinkcaps = gst_pad_get_caps_reffed (sinkpad); if (!gst_caps_is_any (sinkcaps)) ret = !gst_pad_accept_caps (sinkpad, caps); From b0ef98001ffafe17b1e2102d78baf59f24c6d644 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Thu, 10 Mar 2011 19:04:51 +0530 Subject: [PATCH 15/34] playbin2: Check if an element accepts requisite caps before selecting In addition to ensuring that an element we want to select in autoplug-select can enter the READY state, we also now check if it can accept the caps we wish to plug it for. This is handy for sinks that need to perform a probe to figure out whether they can actually handle a given format. --- gst/playback/gstplaybin2.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index 1cd9d5b489..05cac2a148 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -3058,6 +3058,7 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad, const gchar *klass; GstPlaySinkType type; GstElement **sinkp; + GstPad *sinkpad; playbin = group->playbin; @@ -3130,6 +3131,20 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad, return GST_AUTOPLUG_SELECT_SKIP; } + if ((sinkpad = gst_element_get_static_pad (element, "sink"))) { + /* Got the sink pad, now let's see if the element actually does accept the + * caps that we have */ + if (!gst_pad_accept_caps (sinkpad, caps)) { + GST_DEBUG_OBJECT (playbin, "%s doesn't accept our caps", + GST_ELEMENT_NAME (element)); + gst_object_unref (sinkpad); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); + return GST_AUTOPLUG_SELECT_SKIP; + } + gst_object_unref (sinkpad); + } + /* remember the sink in the group now, the element is floating, we take * ownership now */ GST_SOURCE_GROUP_LOCK (group); From 9c13edef4e0fbd5c4c8ed3b31b4776120030134c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 16 Mar 2011 15:27:51 +0100 Subject: [PATCH 16/34] playbin2: Check if an already existing sink supports the non-raw format too Before we were assuming that a sink will always support all non-raw formats in a single stream. --- gst/playback/gstplaybin2.c | 100 +++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index 05cac2a148..05a2294b0d 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -3045,6 +3045,33 @@ done: return ret; } +static gboolean +sink_accepts_caps (GstElement * sink, GstCaps * caps) +{ + GstPad *sinkpad; + + /* ... activate it ... We do this before adding it to the bin so that we + * don't accidentally make it post error messages that will stop + * everything. */ + if (GST_STATE (sink) < GST_STATE_READY && + gst_element_set_state (sink, + GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) { + return FALSE; + } + + if ((sinkpad = gst_element_get_static_pad (sink, "sink"))) { + /* Got the sink pad, now let's see if the element actually does accept the + * caps that we have */ + if (!gst_pad_accept_caps (sinkpad, caps)) { + gst_object_unref (sinkpad); + return FALSE; + } + gst_object_unref (sinkpad); + } + + return TRUE; +} + /* We are asked to select an element. See if the next element to check * is a sink. If this is the case, we see if the sink works by setting it to * READY. If the sink works, we return SELECT_EXPOSE to make decodebin @@ -3058,7 +3085,6 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad, const gchar *klass; GstPlaySinkType type; GstElement **sinkp; - GstPad *sinkpad; playbin = group->playbin; @@ -3105,62 +3131,50 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad, /* now see if we already have a sink element */ GST_SOURCE_GROUP_LOCK (group); if (*sinkp) { - GST_DEBUG_OBJECT (playbin, "we already have a pending sink, expose pad"); - /* for now, just assume that we can link the pad to this same sink. FIXME, - * check that we can link this new pad to this sink as well. */ - GST_SOURCE_GROUP_UNLOCK (group); - return GST_AUTOPLUG_SELECT_EXPOSE; + GstElement *sink = gst_object_ref (*sinkp); + + if (sink_accepts_caps (sink, caps)) { + GST_DEBUG_OBJECT (playbin, + "Existing sink '%s' accepts caps: %" GST_PTR_FORMAT, + GST_ELEMENT_NAME (sink), caps); + gst_object_unref (sink); + GST_SOURCE_GROUP_UNLOCK (group); + return GST_AUTOPLUG_SELECT_EXPOSE; + } else { + GST_DEBUG_OBJECT (playbin, + "Existing sink '%s' does not accept caps: %" GST_PTR_FORMAT, + GST_ELEMENT_NAME (sink), caps); + gst_object_unref (sink); + GST_SOURCE_GROUP_UNLOCK (group); + return GST_AUTOPLUG_SELECT_SKIP; + } } GST_DEBUG_OBJECT (playbin, "we have no pending sink, try to create one"); - GST_SOURCE_GROUP_UNLOCK (group); if ((element = gst_element_factory_create (factory, NULL)) == NULL) { GST_WARNING_OBJECT (playbin, "Could not create an element from %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + GST_SOURCE_GROUP_UNLOCK (group); return GST_AUTOPLUG_SELECT_SKIP; } - /* ... activate it ... We do this before adding it to the bin so that we - * don't accidentally make it post error messages that will stop - * everything. */ - if ((gst_element_set_state (element, - GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) { - GST_WARNING_OBJECT (playbin, "Couldn't set %s to READY", - GST_ELEMENT_NAME (element)); + /* Check if the selected sink actually supports the + * caps and can be set to READY*/ + if (!sink_accepts_caps (element, caps)) { + gst_element_set_state (element, GST_STATE_NULL); gst_object_unref (element); + GST_SOURCE_GROUP_UNLOCK (group); return GST_AUTOPLUG_SELECT_SKIP; } - if ((sinkpad = gst_element_get_static_pad (element, "sink"))) { - /* Got the sink pad, now let's see if the element actually does accept the - * caps that we have */ - if (!gst_pad_accept_caps (sinkpad, caps)) { - GST_DEBUG_OBJECT (playbin, "%s doesn't accept our caps", - GST_ELEMENT_NAME (element)); - gst_object_unref (sinkpad); - gst_element_set_state (element, GST_STATE_NULL); - gst_object_unref (element); - return GST_AUTOPLUG_SELECT_SKIP; - } - gst_object_unref (sinkpad); - } - /* remember the sink in the group now, the element is floating, we take - * ownership now */ - GST_SOURCE_GROUP_LOCK (group); - if (*sinkp == NULL) { - /* store the sink in the group, we will configure it later when we - * reconfigure the sink */ - GST_DEBUG_OBJECT (playbin, "remember sink"); - gst_object_ref_sink (element); - *sinkp = element; - } else { - /* some other thread configured a sink while we were testing the sink, set - * the sink back to NULL and assume we can use the other sink */ - GST_DEBUG_OBJECT (playbin, "another sink was found, expose pad"); - gst_element_set_state (element, GST_STATE_NULL); - gst_object_unref (element); - } + * ownership now + * + * store the sink in the group, we will configure it later when we + * reconfigure the sink */ + GST_DEBUG_OBJECT (playbin, "remember sink"); + gst_object_ref_sink (element); + *sinkp = element; GST_SOURCE_GROUP_UNLOCK (group); /* tell decodebin to expose the pad because we are going to use this From 2c057f745f13eaae6dbb08df374cb32b867327f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 15 Mar 2011 14:45:03 +0100 Subject: [PATCH 17/34] playsink: Remember automatically created sinks for future reconfigures Also allow reuse of sink elements in error cases. --- gst/playback/gstplaysink.c | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index 5ba637ac40..169a541190 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -1215,6 +1215,8 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async) chain->sink = try_element (playsink, elem, TRUE); } } + if (chain->sink) + playsink->video_sink = gst_object_ref (chain->sink); } if (chain->sink == NULL) goto no_sinks; @@ -1360,6 +1362,8 @@ link_failed: (NULL), ("Failed to configure the video sink.")); /* checking sink made it READY */ gst_element_set_state (chain->sink, GST_STATE_NULL); + /* Remove chain from the bin to allow reuse later */ + gst_bin_remove (bin, chain->sink); free_chain ((GstPlayChain *) chain); return NULL; } @@ -1486,6 +1490,9 @@ gen_text_chain (GstPlaySink * playsink) gst_play_sink_find_property_sinks (playsink, chain->sink, "sync", G_TYPE_BOOLEAN))) g_object_set (elem, "sync", TRUE, NULL); + + if (!textsinkpad) + gst_bin_remove (bin, chain->sink); } else { GST_WARNING_OBJECT (playsink, "can't find async property in custom text sink"); @@ -1671,6 +1678,8 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) chain->sink = try_element (playsink, elem, TRUE); } } + if (chain->sink) + playsink->audio_sink = gst_object_ref (chain->sink); } if (chain->sink == NULL) goto no_sinks; @@ -1885,6 +1894,8 @@ link_failed: (NULL), ("Failed to configure the audio sink.")); /* checking sink made it READY */ gst_element_set_state (chain->sink, GST_STATE_NULL); + /* Remove chain from the bin to allow reuse later */ + gst_bin_remove (bin, chain->sink); free_chain ((GstPlayChain *) chain); return NULL; } @@ -2211,6 +2222,13 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) } add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); + + /* Remove the sink from the bin to keep its state + * and unparent it to allow reuse */ + if (playsink->videochain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->videochain->chain.bin), + playsink->videochain->sink); + activate_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); free_chain ((GstPlayChain *) playsink->videochain); playsink->videochain = NULL; @@ -2355,6 +2373,13 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) } add_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); + + /* Remove the sink from the bin to keep its state + * and unparent it to allow reuse */ + if (playsink->audiochain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->audiochain->chain.bin), + playsink->audiochain->sink); + activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); disconnect_chain (playsink->audiochain, playsink); playsink->audiochain->volume = NULL; @@ -3275,6 +3300,27 @@ gst_play_sink_change_state (GstElement * element, GstStateChange transition) * so they may be re-used faster next time/url around. * when really going to NULL, clean up everything completely. */ if (transition == GST_STATE_CHANGE_READY_TO_NULL) { + + /* Unparent the sinks to allow reuse */ + if (playsink->videochain && playsink->videochain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->videochain->chain.bin), + playsink->videochain->sink); + if (playsink->audiochain && playsink->audiochain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->audiochain->chain.bin), + playsink->audiochain->sink); + if (playsink->textchain && playsink->textchain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->textchain->chain.bin), + playsink->textchain->sink); + + if (playsink->audio_sink != NULL) + gst_element_set_state (playsink->audio_sink, GST_STATE_NULL); + if (playsink->video_sink != NULL) + gst_element_set_state (playsink->video_sink, GST_STATE_NULL); + if (playsink->visualisation != NULL) + gst_element_set_state (playsink->visualisation, GST_STATE_NULL); + if (playsink->text_sink != NULL) + gst_element_set_state (playsink->text_sink, GST_STATE_NULL); + free_chain ((GstPlayChain *) playsink->videodeinterlacechain); playsink->videodeinterlacechain = NULL; free_chain ((GstPlayChain *) playsink->videochain); From 2ab592bac9054859172e4aa7336997b306fa4ba8 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 23 Mar 2011 11:13:57 -0300 Subject: [PATCH 18/34] tests: video: Add a test for checking rgb caps creation This new test for checking rgb caps creation exposes a regression --- tests/check/libs/video.c | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/check/libs/video.c b/tests/check/libs/video.c index eedab1c772..d0115e39f9 100644 --- a/tests/check/libs/video.c +++ b/tests/check/libs/video.c @@ -491,6 +491,46 @@ GST_START_TEST (test_video_formats) GST_END_TEST; +GST_START_TEST (test_video_formats_rgb) +{ + gint width, height, framerate_n, framerate_d, par_n, par_d; + GstCaps *caps = + gst_video_format_new_caps (GST_VIDEO_FORMAT_RGB, 800, 600, 0, 1, 1, 1); + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + + fail_unless (gst_structure_get_int (structure, "width", &width)); + fail_unless (gst_structure_get_int (structure, "height", &height)); + fail_unless (gst_structure_get_fraction (structure, "framerate", &framerate_n, + &framerate_d)); + fail_unless (gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_n, &par_d)); + + fail_unless (width == 800); + fail_unless (height == 600); + fail_unless (framerate_n == 0); + fail_unless (framerate_d == 1); + fail_unless (par_n == 1); + fail_unless (par_d == 1); + + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_video_template_caps) +{ +/* + GstCaps *caps = + gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB); + gst_caps_unref (caps); +*/ +} + +GST_END_TEST; + + GST_START_TEST (test_dar_calc) { guint display_ratio_n, display_ratio_d; @@ -734,6 +774,8 @@ video_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_video_formats); + tcase_add_test (tc_chain, test_video_formats_rgb); + tcase_add_test (tc_chain, test_video_template_caps); tcase_add_test (tc_chain, test_dar_calc); tcase_add_test (tc_chain, test_parse_caps_rgb); tcase_add_test (tc_chain, test_events); From 78e8b33c388e7297bf300eada8564ff624b39c8f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 23 Mar 2011 12:02:35 -0300 Subject: [PATCH 19/34] video: Getting component offsets without dimensions is fine if it is not YUV This fixes a regression that an assertion would happen if gst_video_get_component_offset would be called with width or height as 0. Calling it with 0 is fine if the format isn't yuv and this was already being used in some other places of video.c --- gst-libs/gst/video/video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c index 83330c0224..fd265a13e6 100644 --- a/gst-libs/gst/video/video.c +++ b/gst-libs/gst/video/video.c @@ -1730,7 +1730,8 @@ gst_video_format_get_component_offset (GstVideoFormat format, { g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); g_return_val_if_fail (component >= 0 && component <= 3, 0); - g_return_val_if_fail (width > 0 && height > 0, 0); + g_return_val_if_fail ((!gst_video_format_is_yuv (format)) || (width > 0 + && height > 0), 0); switch (format) { case GST_VIDEO_FORMAT_I420: From 6b4d788bb5489e4a3a8ced88e360de7e0e7b8833 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 23 Mar 2011 12:02:42 -0300 Subject: [PATCH 20/34] video: adds missing function to win32 def --- win32/common/libgstvideo.def | 1 + 1 file changed, 1 insertion(+) diff --git a/win32/common/libgstvideo.def b/win32/common/libgstvideo.def index ef663d2f0e..0f09b80f71 100644 --- a/win32/common/libgstvideo.def +++ b/win32/common/libgstvideo.def @@ -21,6 +21,7 @@ EXPORTS gst_video_format_is_yuv gst_video_format_new_caps gst_video_format_new_caps_interlaced + gst_video_format_new_template_caps gst_video_format_parse_caps gst_video_format_parse_caps_interlaced gst_video_format_to_fourcc From 8f2aea0fe418842bb58e77028c66c9eda8eb71b5 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 23 Mar 2011 12:42:04 -0300 Subject: [PATCH 21/34] tests: video: Uncommenting test Pushed a commented test by accident, uncommenting it. --- tests/check/libs/video.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/check/libs/video.c b/tests/check/libs/video.c index d0115e39f9..34d28e049a 100644 --- a/tests/check/libs/video.c +++ b/tests/check/libs/video.c @@ -521,11 +521,8 @@ GST_END_TEST; GST_START_TEST (test_video_template_caps) { -/* - GstCaps *caps = - gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB); + GstCaps *caps = gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB); gst_caps_unref (caps); -*/ } GST_END_TEST; From df886c0622257bb8635e5bd0fc7fc3da20bfc3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 24 Mar 2011 14:03:31 +0100 Subject: [PATCH 22/34] playsink: Only add a queue before the audio sink if visualizations are enabled The queue is not needed otherwise and will add some delay to track switches. --- gst/playback/gstplaysink.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index 169a541190..879f9c49f6 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -1645,7 +1645,7 @@ notify_mute_cb (GObject * object, GParamSpec * pspec, GstPlaySink * playsink) * +-------------------------------------------------------------+ */ static GstPlayAudioChain * -gen_audio_chain (GstPlaySink * playsink, gboolean raw) +gen_audio_chain (GstPlaySink * playsink, gboolean raw, gboolean queue) { GstPlayAudioChain *chain; GstBin *bin; @@ -1691,19 +1691,24 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) /* we have to add a queue when we need to decouple for the video sink in * visualisations */ - GST_DEBUG_OBJECT (playsink, "adding audio queue"); - chain->queue = gst_element_factory_make ("queue", "aqueue"); - if (chain->queue == NULL) { - post_missing_element_message (playsink, "queue"); - GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, - (_("Missing element '%s' - check your GStreamer installation."), - "queue"), ("audio playback and visualizations might not work")); + if (queue) { + GST_DEBUG_OBJECT (playsink, "adding audio queue"); + chain->queue = gst_element_factory_make ("queue", "aqueue"); + if (chain->queue == NULL) { + post_missing_element_message (playsink, "queue"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "queue"), ("audio playback and visualizations might not work")); + head = chain->sink; + prev = NULL; + } else { + g_object_set (chain->queue, "silent", TRUE, NULL); + gst_bin_add (bin, chain->queue); + prev = head = chain->queue; + } + } else { head = chain->sink; prev = NULL; - } else { - g_object_set (chain->queue, "silent", TRUE, NULL); - gst_bin_add (bin, chain->queue); - prev = head = chain->queue; } /* find ts-offset element */ @@ -2393,7 +2398,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) if (!playsink->audiochain) { GST_DEBUG_OBJECT (playsink, "creating new audio chain"); - playsink->audiochain = gen_audio_chain (playsink, raw); + playsink->audiochain = gen_audio_chain (playsink, raw, need_vis); } if (!playsink->audio_sinkpad_stream_synchronizer) { From 65320a04abec3afd7de27f93713a7a27932d723b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 24 Mar 2011 14:21:01 +0100 Subject: [PATCH 23/34] Revert "playsink: Only add a queue before the audio sink if visualizations are enabled" This reverts commit df886c0622257bb8635e5bd0fc7fc3da20bfc3be. --- gst/playback/gstplaysink.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index 879f9c49f6..169a541190 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -1645,7 +1645,7 @@ notify_mute_cb (GObject * object, GParamSpec * pspec, GstPlaySink * playsink) * +-------------------------------------------------------------+ */ static GstPlayAudioChain * -gen_audio_chain (GstPlaySink * playsink, gboolean raw, gboolean queue) +gen_audio_chain (GstPlaySink * playsink, gboolean raw) { GstPlayAudioChain *chain; GstBin *bin; @@ -1691,24 +1691,19 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw, gboolean queue) /* we have to add a queue when we need to decouple for the video sink in * visualisations */ - if (queue) { - GST_DEBUG_OBJECT (playsink, "adding audio queue"); - chain->queue = gst_element_factory_make ("queue", "aqueue"); - if (chain->queue == NULL) { - post_missing_element_message (playsink, "queue"); - GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, - (_("Missing element '%s' - check your GStreamer installation."), - "queue"), ("audio playback and visualizations might not work")); - head = chain->sink; - prev = NULL; - } else { - g_object_set (chain->queue, "silent", TRUE, NULL); - gst_bin_add (bin, chain->queue); - prev = head = chain->queue; - } - } else { + GST_DEBUG_OBJECT (playsink, "adding audio queue"); + chain->queue = gst_element_factory_make ("queue", "aqueue"); + if (chain->queue == NULL) { + post_missing_element_message (playsink, "queue"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "queue"), ("audio playback and visualizations might not work")); head = chain->sink; prev = NULL; + } else { + g_object_set (chain->queue, "silent", TRUE, NULL); + gst_bin_add (bin, chain->queue); + prev = head = chain->queue; } /* find ts-offset element */ @@ -2398,7 +2393,7 @@ gst_play_sink_reconfigure (GstPlaySink * playsink) if (!playsink->audiochain) { GST_DEBUG_OBJECT (playsink, "creating new audio chain"); - playsink->audiochain = gen_audio_chain (playsink, raw, need_vis); + playsink->audiochain = gen_audio_chain (playsink, raw); } if (!playsink->audio_sinkpad_stream_synchronizer) { From c27cd709bfe1f14fb8caf434773c5686d703eb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 24 Mar 2011 14:22:00 +0100 Subject: [PATCH 24/34] playsink: Update comment about why an audio queue is needed --- gst/playback/gstplaysink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index 169a541190..326baa6917 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -1690,7 +1690,7 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) gst_bin_add (bin, chain->sink); /* we have to add a queue when we need to decouple for the video sink in - * visualisations */ + * visualisations and for streamsynchronizer */ GST_DEBUG_OBJECT (playsink, "adding audio queue"); chain->queue = gst_element_factory_make ("queue", "aqueue"); if (chain->queue == NULL) { From 33016b097b79cba42f05f1168a1a4f61af53971f Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 24 Mar 2011 18:48:59 +0200 Subject: [PATCH 25/34] Automatic update of common submodule From 6aec6b9 to 6aaa286 --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 6aec6b9716..6aaa286970 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 6aec6b9716c184c60c4bc6a5916a2471cfa8c8cd +Subproject commit 6aaa286970e59ed89bd69544f2ee10551f377cb6 From 45024097e1914566b4467e90aa93d1fbec76d4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 25 Mar 2011 09:03:13 +0100 Subject: [PATCH 26/34] Automatic update of common submodule From 6aaa286 to d8814b6 --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 6aaa286970..d8814b6c7f 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 6aaa286970e59ed89bd69544f2ee10551f377cb6 +Subproject commit d8814b6c7fb8e037bd19bff6a2698f55ddb2b311 From 17bd3da492209106d70177c88073e44c09e86bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 25 Mar 2011 09:29:38 +0100 Subject: [PATCH 27/34] Automatic update of common submodule From d8814b6 to b77e2bf --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index d8814b6c7f..b77e2bfbb7 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit d8814b6c7fb8e037bd19bff6a2698f55ddb2b311 +Subproject commit b77e2bfbb78e1093d39b7714572ed364e46df53c From 7a4ffb493cee838836587f0dce84b968a489f608 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Fri, 25 Feb 2011 16:46:29 +0100 Subject: [PATCH 28/34] docs: Add an interlaced video design document --- docs/design/part-interlaced-video.txt | 88 +++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs/design/part-interlaced-video.txt diff --git a/docs/design/part-interlaced-video.txt b/docs/design/part-interlaced-video.txt new file mode 100644 index 0000000000..caef5330e5 --- /dev/null +++ b/docs/design/part-interlaced-video.txt @@ -0,0 +1,88 @@ +Interlaced Video +================ + +Video buffers have a number of states identifiable through a combination of caps +and buffer flags. + +Possible states: +- Progressive +- Interlaced + - Plain + - One field + - Two fields + - Three fields - this should be a progressive buffer with a repeated 'first' + field that can be used for telecine pulldown + - Telecine + - One field + - Two fields + - Progressive + - Interlaced (a.k.a. 'mixed'; the fields are from different frames) + - Three fields - this should be a progressive buffer with a repeated 'first' + field that can be used for telecine pulldown + +Note: it can be seen that the different between the plain interlaced and +telecine states is that in the telecine state, buffers containing two fields may +be progressive. + +Tools for identification: +- Caps + - interlaced - boolean + - interlacing-method - string - "unknown"/"telecine" +- Flags - GST_VIDEO_BUFFER_... + - TFF + - RFF + - ONEFIELD + - PROGRESSIVE + + +Identification of Buffer States +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Note that flags are not necessarily interpreted in the same way for all +different states nor are they necessarily required nor make sense in all cases. + + +Progressive +........... + +If the caps have no interlaced field, or have interlaced=false, then the buffer +is progressive. Note the possibility for progressive buffers in telecine streams +as well. + + +Plain Interlaced +................ + +If the caps have interlaced=true and either do not contain the +interlacing-method field or contain interlacing-method=unknown, then the buffer +is plain interlaced. + +GST_VIDEO_BUFFER_TFF indicates whether the top or bottom field is to be +displayed first. The timestamp on the buffer corresponds to the first field. +(FIXME - is the duration of the buffer the duration of both fields; each field's +duration is half the buffer duration) + +GST_VIDEO_BUFFER_RFF indicates that the first field (indicated by the TFF flag) +should be repeated. This is generally only used for telecine purposes but as the +telecine state was added long after the interlaced state was added and defined, +this flag remains valid for plain interlaced buffers. + +GST_VIDEO_BUFFER_ONEFIELD means that only the field indicated through the TFF +flag is to be used. The other field should be ignored. + + +Telecine +........ + +If the caps have interlaced=true and interlacing-method=telecine then the +buffers are in some form of telecine state. + +The TFF, RFF and ONEFIELD flags have the same semantics as for the plain +interlaced state, however, for the telecine state require one additional flag to +be able to identify progressive buffers. + +GST_VIDEO_BUFFER_PROGRESSIVE means that the buffer containing two fields is a +progressive frame. The implication is that if this flag is not set, the buffer +is an 'interlaced' or 'mixed' buffer that contains two fields that, when +combined with fields from adjacent buffers, allow reconstruction of progressive +frames. From 63bd8ff6057c871e25fa27412215e1adbe51f683 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 25 Mar 2011 11:06:35 +0200 Subject: [PATCH 29/34] docs: do xrefs for non installed books too Get the xrefs from the builddir for the books in the same package. This fixes the cross references if one does not have the docs already installed. --- docs/plugins/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 9beea7e55f..c987b85bf3 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -48,7 +48,8 @@ SCAN_OPTIONS= MKDB_OPTIONS=--sgml-mode # Extra options to supply to gtkdoc-fixref. -FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ +FIXXREF_OPTIONS=--extra-dir=$(top_builddir)/docs/libs/html \ + --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ --extra-dir=$(GST_PREFIX)/share/gtk-doc/html \ --extra-dir=$(datadir)/gtk-doc/html From b1eead394dc5823a90e3d800136c1ce9d169eb71 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 25 Mar 2011 14:55:52 +0200 Subject: [PATCH 30/34] Automatic update of common submodule From b77e2bf to 193b717 --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index b77e2bfbb7..193b7176e6 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit b77e2bfbb78e1093d39b7714572ed364e46df53c +Subproject commit 193b7176e61160d78a967884f1b20af76d1c7379 From 4e60cce2b5ebfbb961e83fd44e92caff1a2c4aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 25 Mar 2011 22:14:44 +0100 Subject: [PATCH 31/34] Automatic update of common submodule From 193b717 to 1ccbe09 --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 193b7176e6..1ccbe098d6 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 193b7176e61160d78a967884f1b20af76d1c7379 +Subproject commit 1ccbe098d6379612fcef09f4000da23585af980a From a7a305a18fe905eadcb70ab2ae3052352bd8c6cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 26 Mar 2011 11:59:54 +0000 Subject: [PATCH 32/34] oggparse: make sure buffer metadata is writable before setting caps on buffers --- ext/ogg/gstoggparse.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ext/ogg/gstoggparse.c b/ext/ogg/gstoggparse.c index ffbba865a1..7945d384e9 100644 --- a/ext/ogg/gstoggparse.c +++ b/ext/ogg/gstoggparse.c @@ -574,6 +574,7 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) GstOggStream *stream = (GstOggStream *) l->data; int j; + /* FIXME: list iteration */ for (j = 1; j < g_list_length (stream->headers); j++) { gst_ogg_parse_append_header (&array, GST_BUFFER (g_list_nth_data (stream->headers, j))); @@ -603,6 +604,7 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) GstOggStream *stream = (GstOggStream *) l->data; GstBuffer *buf = GST_BUFFER (stream->headers->data); + buf = gst_buffer_make_metadata_writable (buf); gst_buffer_set_caps (buf, caps); result = gst_pad_push (ogg->srcpad, buf); @@ -613,9 +615,12 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) GstOggStream *stream = (GstOggStream *) l->data; int j; + /* FIXME: list iteration */ for (j = 1; j < g_list_length (stream->headers); j++) { GstBuffer *buf = GST_BUFFER (g_list_nth_data (stream->headers, j)); + + buf = gst_buffer_make_metadata_writable (buf); gst_buffer_set_caps (buf, caps); result = gst_pad_push (ogg->srcpad, buf); @@ -646,7 +651,7 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) for (k = stream->unknown_pages; k != NULL; k = k->next) { GstBuffer *buf; - buf = GST_BUFFER (k->data); + buf = gst_buffer_make_metadata_writable (GST_BUFFER (k->data)); gst_buffer_set_caps (buf, caps); result = gst_pad_push (ogg->srcpad, buf); if (result != GST_FLOW_OK) @@ -666,10 +671,12 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) if (stream->stored_buffers) { int j; + /* FIXME: list iteration */ for (j = 0; j < g_list_length (stream->stored_buffers); j++) { GstBuffer *buf = GST_BUFFER (g_list_nth_data (stream->stored_buffers, j)); + buf = gst_buffer_make_metadata_writable (buf); gst_buffer_set_caps (buf, ogg->caps); GST_BUFFER_TIMESTAMP (buf) = buffertimestamp; if (!keyframe) { @@ -686,6 +693,7 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) stream->stored_buffers = NULL; } + pagebuffer = gst_buffer_make_metadata_writable (pagebuffer); gst_buffer_set_caps (pagebuffer, ogg->caps); if (!keyframe) { GST_BUFFER_FLAG_SET (pagebuffer, GST_BUFFER_FLAG_DELTA_UNIT); @@ -693,7 +701,7 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) keyframe = FALSE; } - result = gst_pad_push (ogg->srcpad, GST_BUFFER (pagebuffer)); + result = gst_pad_push (ogg->srcpad, pagebuffer); if (result != GST_FLOW_OK) return result; } From 03ea1bea4ed9fac889e1e14529c4dcdb9acfa9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 26 Mar 2011 12:01:05 +0000 Subject: [PATCH 33/34] tests: ignore new libsabi test binary --- tests/check/libs/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/check/libs/.gitignore b/tests/check/libs/.gitignore index 5e807df6a9..e649eb33c6 100644 --- a/tests/check/libs/.gitignore +++ b/tests/check/libs/.gitignore @@ -3,6 +3,7 @@ audio cddabasesrc fft gstlibscpp +libsabi mixer navigation netbuffer From 5aa02968c9593f1144a801ffb52aef9f8fa688a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 26 Mar 2011 19:36:50 +0000 Subject: [PATCH 34/34] oggparse: fix list iteration code Not that it really matters, but let's fix it before someone notices and makes fun of us. --- ext/ogg/gstoggparse.c | 56 +++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/ext/ogg/gstoggparse.c b/ext/ogg/gstoggparse.c index 7945d384e9..eae0acdf67 100644 --- a/ext/ogg/gstoggparse.c +++ b/ext/ogg/gstoggparse.c @@ -572,12 +572,11 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) for (l = ogg->oggstreams; l != NULL; l = l->next) { GstOggStream *stream = (GstOggStream *) l->data; - int j; + GList *j; - /* FIXME: list iteration */ - for (j = 1; j < g_list_length (stream->headers); j++) { - gst_ogg_parse_append_header (&array, - GST_BUFFER (g_list_nth_data (stream->headers, j))); + /* already appended the first header, now do headers 2-N */ + for (j = stream->headers->next; j != NULL; j = j->next) { + gst_ogg_parse_append_header (&array, GST_BUFFER (j->data)); count++; } } @@ -613,12 +612,11 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) } for (l = ogg->oggstreams; l != NULL; l = l->next) { GstOggStream *stream = (GstOggStream *) l->data; - int j; + GList *j; - /* FIXME: list iteration */ - for (j = 1; j < g_list_length (stream->headers); j++) { - GstBuffer *buf = - GST_BUFFER (g_list_nth_data (stream->headers, j)); + /* pushed the first one for each stream already, now do 2-N */ + for (j = stream->headers->next; j != NULL; j = j->next) { + GstBuffer *buf = GST_BUFFER (j->data); buf = gst_buffer_make_metadata_writable (buf); gst_buffer_set_caps (buf, caps); @@ -668,29 +666,25 @@ gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) stream->stored_buffers = g_list_append (stream->stored_buffers, pagebuffer); } else { - if (stream->stored_buffers) { - int j; + while (stream->stored_buffers) { + GstBuffer *buf = stream->stored_buffers->data; - /* FIXME: list iteration */ - for (j = 0; j < g_list_length (stream->stored_buffers); j++) { - GstBuffer *buf = - GST_BUFFER (g_list_nth_data (stream->stored_buffers, j)); - - buf = gst_buffer_make_metadata_writable (buf); - gst_buffer_set_caps (buf, ogg->caps); - GST_BUFFER_TIMESTAMP (buf) = buffertimestamp; - if (!keyframe) { - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); - } else { - keyframe = FALSE; - } - - result = gst_pad_push (ogg->srcpad, buf); - if (result != GST_FLOW_OK) - return result; + buf = gst_buffer_make_metadata_writable (buf); + gst_buffer_set_caps (buf, ogg->caps); + GST_BUFFER_TIMESTAMP (buf) = buffertimestamp; + if (!keyframe) { + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + } else { + keyframe = FALSE; } - g_list_free (stream->stored_buffers); - stream->stored_buffers = NULL; + + result = gst_pad_push (ogg->srcpad, buf); + if (result != GST_FLOW_OK) + return result; + + stream->stored_buffers = + g_list_delete_link (stream->stored_buffers, + stream->stored_buffers); } pagebuffer = gst_buffer_make_metadata_writable (pagebuffer);