mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-03 16:09:39 +00:00
49deb0c05d
Original commit message from CVS: * configure.ac: * ext/alsa/gstalsamixerelement.c: (gst_alsa_mixer_element_class_init): * ext/alsa/gstalsasink.c: (gst_alsasink_class_init): * ext/alsa/gstalsasrc.c: (gst_alsasrc_class_init): * ext/cdparanoia/gstcdparanoiasrc.c: (gst_cd_paranoia_src_class_init): * ext/gio/gstgiosink.c: (gst_gio_sink_class_init): * ext/gio/gstgiosrc.c: (gst_gio_src_class_init): * ext/gio/gstgiostreamsink.c: (gst_gio_stream_sink_class_init): * ext/gio/gstgiostreamsrc.c: (gst_gio_stream_src_class_init): * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_class_init): * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_class_init): * ext/ogg/gstoggmux.c: (gst_ogg_mux_class_init): * ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init): * ext/pango/gsttextrender.c: (gst_text_render_class_init): * ext/theora/theoradec.c: (gst_theora_dec_class_init): * ext/theora/theoraenc.c: (gst_theora_enc_class_init): * ext/theora/theoraparse.c: (gst_theora_parse_class_init): * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_class_init): * gst-libs/gst/audio/gstaudiofiltertemplate.c: (gst_audio_filter_template_class_init): * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_class_init): * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_class_init): * gst-libs/gst/cdda/gstcddabasesrc.c: (gst_cdda_base_src_class_init): * gst-libs/gst/interfaces/mixertrack.c: (gst_mixer_track_class_init): * gst-libs/gst/rtp/gstbasertpdepayload.c: (gst_base_rtp_depayload_class_init): * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_class_init): * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_class_init): * gst/audiorate/gstaudiorate.c: (gst_audio_rate_class_init): * gst/audioresample/gstaudioresample.c: (gst_audioresample_class_init): * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audio_test_src_class_init): * gst/gdp/gstgdppay.c: (gst_gdp_pay_class_init): * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init): * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), (preroll_unlinked): * gst/playback/gstplaybin.c: (gst_play_bin_class_init): * gst/playback/gstplaybin2.c: (gst_play_bin_class_init): * gst/playback/gstplaysink.c: (gst_play_sink_class_init): * gst/playback/gstqueue2.c: (gst_queue_class_init): * gst/playback/gststreaminfo.c: (gst_stream_info_class_init): * gst/playback/gststreamselector.c: (gst_selector_pad_class_init), (gst_stream_selector_class_init): * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_class_init): * gst/subparse/gstsubparse.c: (gst_sub_parse_class_init): * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init): * gst/tcp/gsttcpclientsink.c: (gst_tcp_client_sink_class_init): * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_class_init): * gst/tcp/gsttcpserversink.c: (gst_tcp_server_sink_class_init): * gst/tcp/gsttcpserversrc.c: (gst_tcp_server_src_class_init): * gst/videorate/gstvideorate.c: (gst_video_rate_class_init): * gst/videoscale/gstvideoscale.c: (gst_video_scale_class_init): * gst/videotestsrc/gstvideotestsrc.c: (gst_video_test_src_class_init): * gst/volume/gstvolume.c: (gst_volume_class_init): * sys/v4l/gstv4lelement.c: (gst_v4lelement_class_init): * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_class_init): * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_class_init): * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init): * sys/ximage/ximagesink.c: (gst_ximagesink_class_init): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_class_init): Use G_PARAM_STATIC_STRINGS everywhere for GParamSpecs that use static strings (i.e. all). This gives us less memory usage, fewer allocations and thus less memory defragmentation. Depend on core CVS for this. Fixes bug #523806.
402 lines
12 KiB
C
402 lines
12 KiB
C
/* GStreamer
|
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <gst/gst.h>
|
|
#include "gststreaminfo.h"
|
|
|
|
GST_DEBUG_CATEGORY_STATIC (gst_streaminfo_debug);
|
|
#define GST_CAT_DEFAULT gst_streaminfo_debug
|
|
|
|
/* props */
|
|
enum
|
|
{
|
|
ARG_0,
|
|
ARG_PAD,
|
|
ARG_TYPE,
|
|
ARG_DECODER,
|
|
ARG_MUTE,
|
|
ARG_CAPS,
|
|
ARG_LANG_CODE,
|
|
ARG_CODEC
|
|
};
|
|
|
|
/* signals */
|
|
enum
|
|
{
|
|
SIGNAL_MUTED,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint gst_stream_info_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
#define GST_TYPE_STREAM_TYPE (gst_stream_type_get_type())
|
|
static GType
|
|
gst_stream_type_get_type (void)
|
|
{
|
|
static GType stream_type_type = 0;
|
|
static const GEnumValue stream_type[] = {
|
|
{GST_STREAM_TYPE_UNKNOWN, "Unknown stream", "unknown"},
|
|
{GST_STREAM_TYPE_AUDIO, "Audio stream", "audio"},
|
|
{GST_STREAM_TYPE_VIDEO, "Video stream", "video"},
|
|
{GST_STREAM_TYPE_TEXT, "Text stream", "text"},
|
|
{GST_STREAM_TYPE_SUBPICTURE, "Subpicture stream", "subpicture"},
|
|
{GST_STREAM_TYPE_ELEMENT,
|
|
"Stream handled by element", "element"},
|
|
{0, NULL, NULL},
|
|
};
|
|
|
|
if (!stream_type_type) {
|
|
stream_type_type = g_enum_register_static ("GstStreamType", stream_type);
|
|
}
|
|
return stream_type_type;
|
|
}
|
|
|
|
static void gst_stream_info_class_init (GstStreamInfoClass * klass);
|
|
static void gst_stream_info_init (GstStreamInfo * stream_info);
|
|
static void gst_stream_info_dispose (GObject * object);
|
|
|
|
static void stream_info_change_state (GstElement * element,
|
|
gint old_state, gint new_state, gpointer data);
|
|
|
|
static void gst_stream_info_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * spec);
|
|
static void gst_stream_info_get_property (GObject * object, guint prop_id,
|
|
GValue * value, GParamSpec * spec);
|
|
|
|
static GObjectClass *parent_class;
|
|
|
|
//static guint gst_stream_info_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
GType
|
|
gst_stream_info_get_type (void)
|
|
{
|
|
static GType gst_stream_info_type = 0;
|
|
|
|
if (!gst_stream_info_type) {
|
|
static const GTypeInfo gst_stream_info_info = {
|
|
sizeof (GstStreamInfoClass),
|
|
NULL,
|
|
NULL,
|
|
(GClassInitFunc) gst_stream_info_class_init,
|
|
NULL,
|
|
NULL,
|
|
sizeof (GstStreamInfo),
|
|
0,
|
|
(GInstanceInitFunc) gst_stream_info_init,
|
|
NULL
|
|
};
|
|
gst_stream_info_type = g_type_register_static (G_TYPE_OBJECT,
|
|
"GstStreamInfo", &gst_stream_info_info, 0);
|
|
}
|
|
|
|
return gst_stream_info_type;
|
|
}
|
|
|
|
static void
|
|
gst_stream_info_class_init (GstStreamInfoClass * klass)
|
|
{
|
|
GObjectClass *gobject_klass;
|
|
|
|
gobject_klass = (GObjectClass *) klass;
|
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
|
|
|
gobject_klass->set_property = gst_stream_info_set_property;
|
|
gobject_klass->get_property = gst_stream_info_get_property;
|
|
|
|
g_object_class_install_property (gobject_klass, ARG_PAD,
|
|
g_param_spec_object ("object", "object",
|
|
"Source Pad or object of the stream", GST_TYPE_OBJECT,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
g_object_class_install_property (gobject_klass, ARG_TYPE,
|
|
g_param_spec_enum ("type", "Type", "Type of the stream",
|
|
GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
g_object_class_install_property (gobject_klass, ARG_DECODER,
|
|
g_param_spec_string ("decoder", "Decoder",
|
|
"The decoder used to decode the stream", NULL,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
g_object_class_install_property (gobject_klass, ARG_MUTE,
|
|
g_param_spec_boolean ("mute", "Mute", "Mute or unmute this stream", FALSE,
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
g_object_class_install_property (gobject_klass, ARG_CAPS,
|
|
g_param_spec_boxed ("caps", "Capabilities",
|
|
"Capabilities (or type) of this stream", GST_TYPE_CAPS,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
g_object_class_install_property (gobject_klass, ARG_LANG_CODE,
|
|
g_param_spec_string ("language-code", "Language code",
|
|
"Language code for this stream, conforming to ISO-639-1", NULL,
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
g_object_class_install_property (gobject_klass, ARG_CODEC,
|
|
g_param_spec_string ("codec", "Codec", "Codec used to encode the stream",
|
|
NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
|
|
|
gst_stream_info_signals[SIGNAL_MUTED] =
|
|
g_signal_new ("muted", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (GstStreamInfoClass, muted), NULL, NULL,
|
|
gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
|
|
|
gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_stream_info_dispose);
|
|
|
|
GST_DEBUG_CATEGORY_INIT (gst_streaminfo_debug, "streaminfo", 0,
|
|
"Playbin Stream Info");
|
|
}
|
|
|
|
|
|
static void
|
|
gst_stream_info_init (GstStreamInfo * stream_info)
|
|
{
|
|
stream_info->object = NULL;
|
|
stream_info->origin = NULL;
|
|
stream_info->type = GST_STREAM_TYPE_UNKNOWN;
|
|
stream_info->decoder = NULL;
|
|
stream_info->mute = FALSE;
|
|
stream_info->caps = NULL;
|
|
}
|
|
|
|
static gboolean
|
|
cb_probe (GstPad * pad, GstEvent * e, gpointer user_data)
|
|
{
|
|
GstStreamInfo *info = user_data;
|
|
|
|
if (GST_EVENT_TYPE (e) == GST_EVENT_TAG) {
|
|
gchar *codec, *lang;
|
|
GstTagList *list;
|
|
|
|
gst_event_parse_tag (e, &list);
|
|
|
|
if (info->type != GST_STREAM_TYPE_AUDIO &&
|
|
gst_tag_list_get_string (list, GST_TAG_VIDEO_CODEC, &codec)) {
|
|
g_free (info->codec);
|
|
info->codec = codec;
|
|
GST_LOG_OBJECT (pad, "codec = %s (video)", codec);
|
|
g_object_notify (G_OBJECT (info), "codec");
|
|
} else if (info->type != GST_STREAM_TYPE_VIDEO &&
|
|
gst_tag_list_get_string (list, GST_TAG_AUDIO_CODEC, &codec)) {
|
|
g_free (info->codec);
|
|
info->codec = codec;
|
|
GST_LOG_OBJECT (pad, "codec = %s (audio)", codec);
|
|
g_object_notify (G_OBJECT (info), "codec");
|
|
} else if (gst_tag_list_get_string (list, GST_TAG_CODEC, &codec)) {
|
|
g_free (info->codec);
|
|
info->codec = codec;
|
|
GST_LOG_OBJECT (pad, "codec = %s (generic)", codec);
|
|
g_object_notify (G_OBJECT (info), "codec");
|
|
}
|
|
if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) {
|
|
g_free (info->langcode);
|
|
info->langcode = lang;
|
|
GST_LOG_OBJECT (pad, "language-code = %s", lang);
|
|
g_object_notify (G_OBJECT (info), "language-code");
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GstStreamInfo *
|
|
gst_stream_info_new (GstObject * object,
|
|
GstStreamType type, const gchar * decoder, const GstCaps * caps)
|
|
{
|
|
GstStreamInfo *info;
|
|
|
|
info = g_object_new (GST_TYPE_STREAM_INFO, NULL);
|
|
|
|
gst_object_ref (object);
|
|
if (GST_IS_PAD (object)) {
|
|
gst_pad_add_event_probe (GST_PAD_CAST (object),
|
|
G_CALLBACK (cb_probe), info);
|
|
}
|
|
info->object = object;
|
|
info->type = type;
|
|
info->decoder = g_strdup (decoder);
|
|
info->origin = object;
|
|
if (caps) {
|
|
info->caps = gst_caps_copy (caps);
|
|
}
|
|
|
|
return info;
|
|
}
|
|
|
|
static void
|
|
gst_stream_info_dispose (GObject * object)
|
|
{
|
|
GstStreamInfo *stream_info;
|
|
|
|
stream_info = GST_STREAM_INFO (object);
|
|
|
|
if (stream_info->object) {
|
|
GstElement *parent;
|
|
|
|
parent = gst_pad_get_parent_element ((GstPad *)
|
|
GST_PAD_CAST (stream_info->object));
|
|
if (parent != NULL) {
|
|
g_signal_handlers_disconnect_by_func (parent,
|
|
(gpointer) stream_info_change_state, stream_info);
|
|
gst_object_unref (parent);
|
|
}
|
|
|
|
gst_object_unref (stream_info->object);
|
|
stream_info->object = NULL;
|
|
}
|
|
stream_info->origin = NULL;
|
|
stream_info->type = GST_STREAM_TYPE_UNKNOWN;
|
|
g_free (stream_info->decoder);
|
|
stream_info->decoder = NULL;
|
|
g_free (stream_info->langcode);
|
|
stream_info->langcode = NULL;
|
|
g_free (stream_info->codec);
|
|
stream_info->codec = NULL;
|
|
if (stream_info->caps) {
|
|
gst_caps_unref (stream_info->caps);
|
|
stream_info->caps = NULL;
|
|
}
|
|
|
|
if (G_OBJECT_CLASS (parent_class)->dispose) {
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
}
|
|
|
|
static void
|
|
stream_info_change_state (GstElement * element,
|
|
gint old_state, gint new_state, gpointer data)
|
|
{
|
|
GstStreamInfo *stream_info = data;
|
|
|
|
if (new_state == GST_STATE_PLAYING) {
|
|
/* state change will annoy us */
|
|
g_return_if_fail (stream_info->mute == TRUE);
|
|
GST_DEBUG_OBJECT (stream_info, "Re-muting pads after state-change");
|
|
//gst_pad_set_active_recursive (GST_PAD (stream_info->object), FALSE);
|
|
g_warning ("FIXME");
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
gst_stream_info_set_mute (GstStreamInfo * stream_info, gboolean mute)
|
|
{
|
|
g_return_val_if_fail (GST_IS_STREAM_INFO (stream_info), FALSE);
|
|
|
|
if (stream_info->type == GST_STREAM_TYPE_ELEMENT) {
|
|
g_warning ("cannot mute element stream");
|
|
return FALSE;
|
|
}
|
|
|
|
if (mute != stream_info->mute) {
|
|
/* nothing really happens here. it looks like gstplaybasebin installs a
|
|
* buffer probe hat drops buffers when muting. but the this removes it self
|
|
* after first call.
|
|
*/
|
|
|
|
stream_info->mute = mute;
|
|
#if 0
|
|
gst_pad_set_active ((GstPad *) GST_PAD_CAST (stream_info->object), !mute);
|
|
#endif
|
|
#if 0
|
|
{
|
|
GstElement *element;
|
|
|
|
element = gst_pad_get_parent_element ((GstPad *)
|
|
GST_PAD_CAST (stream_info->object));
|
|
if (element) {
|
|
if (mute) {
|
|
g_signal_connect (element, "state-changed",
|
|
G_CALLBACK (stream_info_change_state), stream_info);
|
|
} else {
|
|
g_signal_handlers_disconnect_by_func (element,
|
|
G_CALLBACK (stream_info_change_state), stream_info);
|
|
}
|
|
gst_object_unref (element);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gst_stream_info_is_mute (GstStreamInfo * stream_info)
|
|
{
|
|
g_return_val_if_fail (GST_IS_STREAM_INFO (stream_info), TRUE);
|
|
|
|
return stream_info->mute;
|
|
}
|
|
|
|
static void
|
|
gst_stream_info_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstStreamInfo *stream_info;
|
|
|
|
g_return_if_fail (GST_IS_STREAM_INFO (object));
|
|
|
|
stream_info = GST_STREAM_INFO (object);
|
|
|
|
switch (prop_id) {
|
|
case ARG_MUTE:
|
|
gst_stream_info_set_mute (stream_info, g_value_get_boolean (value));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_stream_info_get_property (GObject * object, guint prop_id, GValue * value,
|
|
GParamSpec * pspec)
|
|
{
|
|
GstStreamInfo *stream_info;
|
|
|
|
g_return_if_fail (GST_IS_STREAM_INFO (object));
|
|
|
|
stream_info = GST_STREAM_INFO (object);
|
|
|
|
switch (prop_id) {
|
|
case ARG_PAD:
|
|
g_value_set_object (value, stream_info->object);
|
|
break;
|
|
case ARG_TYPE:
|
|
g_value_set_enum (value, stream_info->type);
|
|
break;
|
|
case ARG_DECODER:
|
|
g_value_set_string (value, stream_info->decoder);
|
|
break;
|
|
case ARG_MUTE:
|
|
g_value_set_boolean (value, stream_info->mute);
|
|
break;
|
|
case ARG_CAPS:
|
|
g_value_set_boxed (value, stream_info->caps);
|
|
break;
|
|
case ARG_LANG_CODE:
|
|
g_value_set_string (value, stream_info->langcode);
|
|
break;
|
|
case ARG_CODEC:
|
|
g_value_set_string (value, stream_info->codec);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|