[gst-devel] new plugin writer's issue
Durgesh Mishra
durgesh.mishra at gmail.com
Thu Feb 18 19:24:56 CET 2010
Hi Mike,
Here is the complete code of the plugin. Sorry there are lot of commented
part in it. I have revisited it several times but not able to find what
could be wrong. Please help me on this.
/*
* GStreamer
* Copyright (C) 2005 Thomas Vander Stichele <thomas at apestaart.org>
* Copyright (C) 2005 Ronald S. Bultje <rbultje at ronald.bitfreak.net>
* Copyright (C) 2010 durgesh <<user at hostname.org>>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
"Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Alternatively, the contents of this file may be used under the
* GNU Lesser General Public License Version 2.1 (the "LGPL"), in
* which case the following provisions apply instead of the ones
* mentioned above:
*
* 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.
*/
/**
* SECTION:element-droidaudiosrc
*
* FIXME:Describe droidaudiosrc here.
*
* <refsect2>
* <title>Example launch line</title>
* |[
* gst-launch -v -m fakesrc ! droidaudiosrc ! fakesink silent=TRUE
* ]|
* </refsect2>
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gst/gst.h>
#include <gst/gstutils.h>
#include "gstdroidaudiosrc.h"
GST_DEBUG_CATEGORY_STATIC (gst_droidaudiosrc_debug);
#define GST_CAT_DEFAULT gst_droidaudiosrc_debug
#define DEFAULT_BUFFERTIME (500*GST_MSECOND) / (GST_USECOND)
#define DEFAULT_LATENCYTIME (50*GST_MSECOND) / (GST_USECOND)
/* Filter signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
PROP_0,
PROP_SILENT
};
/* the capabilities of the inputs and outputs.
*
* describe the real formats here.
*/
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("ANY")
);
/*
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("ANY")
);*/
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
//GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-raw-int, "
"signed = (boolean) { TRUE, FALSE }, "
"width = (int) 16, "
"depth = (int) 16, "
"rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ];")
);
//static GstElementClass *parent_class = NULL;
GST_BOILERPLATE (Gstdroidaudiosrc, gst_droidaudiosrc, GstElement,
GST_TYPE_ELEMENT);
static void gst_droidaudiosrc_reset (Gstdroidaudiosrc * asrc);
static void gst_droidaudiosrc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_droidaudiosrc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_droidaudiosrc_set_caps (GstPad * pad, GstCaps * caps);
static GstFlowReturn gst_droidaudiosrc_chain (GstPad * pad, GstBuffer *
buf);
static GstCaps *gst_droidsrc_getcaps (GstBaseSrc * bsrc);
static gboolean gst_droidsrc_open (GstAudioSrc * droidsrc);
static gboolean gst_droidsrc_prepare (GstAudioSrc * droidsrc,
GstRingBufferSpec * spec);
static gboolean gst_droidsrc_unprepare (GstAudioSrc * droidsrc);
static gboolean gst_droidsrc_close (GstAudioSrc * droidsrc);
static guint gst_droidsrc_read (GstAudioSrc * droidsrc, gpointer data, guint
length);
static guint gst_droidsrc_delay (GstAudioSrc * droidsrc);
static void gst_droidsrc_reset (GstAudioSrc * droidsrc);
static void gst_droidaudiosrc_finalise(GObject* object);
static void gst_droidaudiosrc_dispose (GObject * object);
/* GObject vmethod implementations */
#define PDB
static void
gst_droidaudiosrc_base_init (gpointer gclass)
{
#ifdef PDB
printf("base_init started");
#endif
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_set_details_simple(element_class,
"droidaudiosrc",
"Src/Audio",
"Input from android audio record",
"durgesh o mishra durgesh.mishra at gmail.com");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
#ifdef PDB
printf("base_init done");
#endif
/* gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));*/
}
/* initialize the droidaudiosrc's class */
static void
gst_droidaudiosrc_class_init (GstdroidaudiosrcClass * klass)
{
#ifdef PDB
printf("class_init started");
#endif
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
//Durgesh
GstBaseSrcClass *gstbasesrc_class;
GstBaseAudioSrcClass *gstbaseaudiosrc_class;
GstAudioSrcClass *gstaudiosrc_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass;
gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
gstaudiosrc_class = (GstAudioSrcClass *) klass;
parent_class = g_type_class_peek_parent (klass);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_droidaudiosrc_dispose);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_droidaudiosrc_finalise);
gobject_class->set_property = gst_droidaudiosrc_set_property;
gobject_class->get_property = gst_droidaudiosrc_get_property;
gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_droidsrc_getcaps);
gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR
(gst_droidaudiosrc_set_caps);
// gstaudiosrc_class->
gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_droidsrc_open);
gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_droidsrc_prepare);
gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_droidsrc_unprepare);
gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_droidsrc_close);
gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_droidsrc_read);
gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_droidsrc_delay);
gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_droidsrc_reset);
#ifdef PDB
printf("class_init done");
#endif
/*
g_object_class_install_property (gobject_class, PROP_SILENT,
g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
FALSE, G_PARAM_READWRITE));*/
}
static void
gst_droidaudiosrc_dispose (GObject * object)
{
#ifdef PDB
printf("droidaudiosrc_dispose started");
#endif
Gstdroidaudiosrc *asrc = GST_DROIDAUDIOSRC (object);
if (asrc->probed_caps) {
gst_caps_unref (asrc->probed_caps);
asrc->probed_caps = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
#ifdef PDB
printf("droidaudiosrc_dispose done");
#endif
}
static guint gst_droidsrc_delay (GstAudioSrc * droidsrc)
{
//Do nothing
#ifdef PDB
printf("delay done");
#endif
return 0;
}
static void
gst_droidaudiosrc_finalise (GObject * object)
{
#ifdef PDB
printf("finalize started");
#endif
Gstdroidaudiosrc *asrc = GST_DROIDAUDIOSRC (object);
gst_droidaudiosrc_reset (asrc);
G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (object));
#ifdef PDB
printf("finalise done");
#endif
}
/* initialize the new element
* instantiate pads and add them to element
* set pad calback functions
* initialize instance structure
*/
static void
gst_droidaudiosrc_reset (Gstdroidaudiosrc * asrc)
{
#ifdef PDB
printf("droidaudiosrc_reset started");
#endif
GST_DEBUG_OBJECT (asrc, "enter");
if (asrc->audiorecord_device != NULL) {
audiorecord_device_release (asrc->audiorecord_device);
asrc->audiorecord_device = NULL;
}
asrc->audiorecord_device = NULL;
asrc->m_init = FALSE;
asrc->m_audiosrc = NULL;
#ifdef PDB
printf("reset done");
#endif
}
static void gst_droidsrc_reset (GstAudioSrc * droidsrc)
{
#ifdef PDB
printf("droidsrc_reset started");
#endif
Gstdroidaudiosrc *asrc = GST_DROIDAUDIOSRC (droidsrc);
GST_DEBUG_OBJECT(asrc,"enter");
gst_droidaudiosrc_reset(asrc);
#ifdef PDB
printf("droidsrc reset done");
#endif
}
static gboolean gst_droidsrc_close (GstAudioSrc * droidsrc)
{
#ifdef PDB
printf("droidsrc_close started");
#endif
Gstdroidaudiosrc *asrc = GST_DROIDAUDIOSRC (droidsrc);
GST_DEBUG_OBJECT (asrc, "enter");
if (asrc->audiorecord_device != NULL) {
GST_DEBUG_OBJECT (asrc, "release audio record device");
audiorecord_device_stop (asrc->audiorecord_device);
audiorecord_device_release (asrc->audiorecord_device);
asrc->audiorecord_device = NULL;
}
#ifdef PDB
printf("droidsrc close done");
#endif
return TRUE;
}
static void
gst_droidaudiosrc_init (Gstdroidaudiosrc * asrc,
GstdroidaudiosrcClass * gclass)
{
#ifdef PDB
printf("droidaudiosrc_init started");
#endif
GST_DEBUG_OBJECT (asrc, "initializing android audio source");
//gst_droidaudiosrc_reset(asrc->audiorecord_device);
gst_droidaudiosrc_reset(asrc);
//This code may require to be deleted.
GstPad* src_pad = gst_pad_new_from_static_template (&src_factory,
"src");
gst_pad_set_getcaps_function (src_pad,
GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
gst_element_add_pad (GST_ELEMENT (asrc), src_pad);
#ifdef PDB
printf("droid src init done");
#endif
/* alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
alsasrc->cached_caps = NULL;
*/
// alsasrc->alsa_lock = g_mutex_new ();
/* filter->sinkpad = gst_pad_new_from_static_template (&sink_factory,
"sink");
gst_pad_set_setcaps_function (filter->sinkpad,
GST_DEBUG_FUNCPTR(gst_droidaudiosrc_set_caps));
gst_pad_set_getcaps_function (filter->sinkpad,
GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
gst_pad_set_chain_function (filter->sinkpad,
GST_DEBUG_FUNCPTR(gst_droidaudiosrc_chain));
filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
gst_pad_set_getcaps_function (filter->srcpad,
GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
filter->silent = FALSE;*/
}
static void
gst_droidaudiosrc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
/*Gstdroidaudiosrc *filter = GST_DROIDAUDIOSRC (object);
switch (prop_id) {
case PROP_SILENT:
filter->silent = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}*/
#ifdef PDB
printf("set property done");
#endif
// Do Nothing
}
static void
gst_droidaudiosrc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
/*Gstdroidaudiosrc *filter = GST_DROIDAUDIOSRC (object);
switch (prop_id) {
case PROP_SILENT:
g_value_set_boolean (value, filter->silent);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}*/
//Do Nothing
#ifdef PDB
printf("get property done");
#endif
}
/* GstElement vmethod implementations */
/* this function handles the link with other elements */
static gboolean
gst_droidaudiosrc_set_caps (GstPad * pad, GstCaps * caps)
{
/* Gstdroidaudiosrc *filter;
GstPad *otherpad;
filter = GST_DROIDAUDIOSRC (gst_pad_get_parent (pad));
otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
gst_object_unref (filter);
return gst_pad_set_caps (otherpad, caps);*/
//do nothing
#ifdef PDB
printf("set caps done");
#endif
return FALSE;
}
static GstCaps *
gst_droidsrc_getcaps (GstBaseSrc * bsrc)
{
GstElementClass *element_class;
GstPadTemplate *pad_template;
Gstdroidaudiosrc *asrc;
GstCaps *caps;
#ifdef PDB
printf("droidaudiosrc_getcaps started");
#endif
asrc = GST_DROIDAUDIOSRC (bsrc);
GST_DEBUG_OBJECT (asrc, "enter,%p", asrc->audiorecord_device);
/*if(asrc->audiorecord_device == NULL || asrc->m_init == FALSE)
{
caps = gst_caps_copy(gst_pad_get_pad_template_caps
(GST_BASE_SRC_PAD(bsrc)));
}
else*/
if (asrc->probed_caps)
caps = gst_caps_copy(asrc->probed_caps);
else
{
caps = gst_caps_new_simple ("audio/x-raw-int",
"signed",G_TYPE_BOOLEAN, FALSE,
"width", G_TYPE_INT, 16,
"depth", G_TYPE_INT, 16,
"rate", G_TYPE_INT,8000 ,
"channels", G_TYPE_INT, 2, NULL);
if (caps && !gst_caps_is_empty(caps)) {
asrc->probed_caps = gst_caps_copy(caps);
}
}
#ifdef PDB
printf("get caps done");
#endif
return caps;
}
/* chain function
* this function does the actual processing
*/
/*
static GstFlowReturn
gst_droidaudiosrc_chain (GstPad * pad, GstBuffer * buf)
{
Gstdroidaudiosrc *filter;
filter = GST_DROIDAUDIOSRC (GST_OBJECT_PARENT (pad));
if (filter->silent == FALSE)
g_print ("I'm plugged, therefore I'm in.\n");
return gst_pad_push (filter->srcpad, buf);
}*/
/* entry point to initialize the plug-in
* initialize the plug-in itself
* register the element factories and other features
*/
static gboolean
droidaudiosrc_init (GstPlugin * droidaudiosrc)
{
#ifdef PDB
printf("droidaudiosrc_init started");
#endif
GST_DEBUG_CATEGORY_INIT (gst_droidaudiosrc_debug, "droidaudiosrc",
0, "Template droidaudiosrc");
#ifdef PDB
printf("audiosrc init done");
#endif
return gst_element_register (droidaudiosrc, "droidaudiosrc",
GST_RANK_NONE,
GST_TYPE_DROIDAUDIOSRC);
}
static gboolean gst_droidsrc_open (GstAudioSrc * droidsrc)
{
Gstdroidaudiosrc *asrc = GST_DROIDAUDIOSRC (droidsrc);
GstBaseAudioSrc *baseaudiosrc = (GstBaseAudioSrc *) asrc;
#ifdef PDB
printf("droidsrc_open started");
#endif
GST_DEBUG_OBJECT (asrc, "enter");
g_return_val_if_fail (asrc != NULL, FALSE);
baseaudiosrc->buffer_time = DEFAULT_BUFFERTIME;
baseaudiosrc->latency_time = DEFAULT_LATENCYTIME;
if (asrc->audiorecord_device == NULL) {
if (asrc->m_audiosrc) {
if (!(asrc->audiorecord_device =
audiorecord_device_open(asrc->m_audiosrc)))
goto failed_creation;
GST_DEBUG_OBJECT (asrc, "open an existed audio record, %p",
asrc->audiorecord_device);
}
else {
if (!(asrc->audiorecord_device = audiorecord_device_create ()))
goto failed_creation;
GST_DEBUG_OBJECT (asrc, "create a new audio record, %p",
asrc->audiorecord_device);
}
}
return TRUE;
/* ERRORS */
failed_creation:
{
GST_ELEMENT_ERROR (asrc, RESOURCE, SETTINGS, (NULL),
("Failed to create AudioRecord"));
return FALSE;
}
}
static gboolean gst_droidsrc_prepare (GstAudioSrc * droidsrc,
GstRingBufferSpec * spec)
{
Gstdroidaudiosrc *asrc;
asrc = GST_DROIDAUDIOSRC (droidsrc);
GST_DEBUG_OBJECT (asrc, "enter");
if( audiorecord_device_set (asrc->audiorecord_device,
3, spec->channels, spec->rate,
spec->segsize) == -1)
goto failed_creation;
asrc->m_init = TRUE;
//audioflinger->m_init = TRUE;
// gst_audioflinger_sink_set_volume (audioflinger,
audioflinger->m_volume);
// gst_audioflinger_sink_set_mute (audioflinger, audioflinger->m_mute);
spec->bytes_per_sample = (spec->width / 8) * spec->channels;
asrc->bytes_per_sample = spec->bytes_per_sample;
GST_DEBUG_OBJECT (asrc,
"channels: %d, rate: %d, width: %d, got segsize: %d, segtotal: %d,
"
"frame count: %d, frame size: %d",
spec->channels, spec->rate, spec->width, spec->segsize,
spec->segtotal,
audiorecord_device_frameCount (asrc->audiorecord_device),
audiorecord_device_frameSize (asrc->audiorecord_device)
);
/* GST_DEBUG_OBJECT (asrc, "pause device");
audiorecord_device_pause (asrc->audiorecord_device);
*/
return TRUE;
/* ERRORS */
failed_creation:
{
GST_ELEMENT_ERROR (asrc, RESOURCE, SETTINGS, (NULL),
("Failed to create Audiorecord for format %d", spec->format));
return FALSE;
}
dodgy_width:
{
GST_ELEMENT_ERROR (asrc, RESOURCE, SETTINGS, (NULL),
("Unhandled width %d", spec->width));
return FALSE;
}
}
static gboolean gst_droidsrc_unprepare (GstAudioSrc * droidsrc)
{
Gstdroidaudiosrc *asrc;
asrc = GST_DROIDAUDIOSRC (droidsrc);
GST_DEBUG_OBJECT (asrc, "enter");
//audioflinger = GST_AUDIOFLINGERSINK (asink);
if (asrc->audiorecord_device != NULL) {
GST_DEBUG_OBJECT (asrc, "release flinger device");
audiorecord_device_stop(asrc->audiorecord_device);
asrc->m_init = FALSE;
}
return TRUE;
}
static guint gst_droidsrc_read (GstAudioSrc * droidsrc, gpointer data, guint
length)
{
Gstdroidaudiosrc *asrc;
asrc = GST_DROIDAUDIOSRC (droidsrc);
//GstAudioFlingerSink *audioflinger;
guint ret = 0;
// audioflinger = GST_AUDIOFLINGERSINK (asink);
GST_INFO_OBJECT (asrc, "read length=%d", length);
if (asrc->audiorecord_device == NULL ||
asrc->m_init == FALSE)
{
GST_WARNING_OBJECT (asrc,
"Cannot write when device isn't initialized. Consume data");
return length;
}
/* FIXME : Instead of using write, we should be using
obtainBuffer/releaseBuffer
* which gives us a more granular feedback. */
ret =
audiorecord_device_read (asrc->audiorecord_device, data,
length);
if (ret == 0) {
GST_WARNING_OBJECT (asrc, "read failure");
ret = length;
}
GST_INFO_OBJECT (asrc, "read=%u", ret);
return ret;
}
/*static guint gst_droidsrc_delay (GstAudioSrc * asrc);
static void gst_droidsrc_reset (GstAudioSrc * asrc);*/
/* PACKAGE: this is usually set by autotools depending on some _INIT macro
* in configure.ac and then written into and defined in config.h, but we can
* just set it ourselves here in case someone doesn't use autotools to
* compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
*/
#ifndef PACKAGE
#define PACKAGE "myfirstdroidaudiosrc"
#endif
GST_PLUGIN_DEFINE (
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"droidaudiosrc",
"Template droidaudiosrc",
droidaudiosrc_init,
VERSION,
"LGPL",
"GStreamer",
"http://gstreamer.net/"
)
Kind Regards
-Durgesh O Mishra
On 18 February 2010 23:41, Michael Smith <msmith at xiph.org> wrote:
> On Thu, Feb 18, 2010 at 9:55 AM, Durgesh Mishra
> <durgesh.mishra at gmail.com> wrote:
> > Hi Mike,
> >
> > The problem is resolved now. Here is something that I did.
> >
> > I took reference of AlsaSrc plugin for writing this DroidAudioSrc plugin.
> >
> > I did write these statements in droidaudiosrc_init() function.
> >
> > GstPad* src_pad = gst_pad_new_from_static_template (&src_factory, "src");
> > gst_pad_set_getcaps_function (src_pad,
> >
> > GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps));
> > gst_element_add_pad (GST_ELEMENT (asrc), src_pad);
>
> You should not be adding the src pad yourself - if you're needing
> this, then that means there's something else wrong in your plugin -
> the base source should be adding the pad for you. If it's not doing
> that, then something isn't initialising properly - and you'll probably
> have many more problems. So you should revert that change, and figure
> out the real cause of your bug.
>
> Mike
>
>
> ------------------------------------------------------------------------------
> Download Intel® Parallel Studio Eval
> Try the new software tools for yourself. Speed compiling, find bugs
> proactively, and fine-tune applications for parallel performance.
> See why Intel Parallel Studio got high marks during beta.
> http://p.sf.net/sfu/intel-sw-dev
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
>
--
"If you only have a hammer, you tend to see every problem as a nail."
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20100218/2a272d45/attachment.htm>
More information about the gstreamer-devel
mailing list