mimic: remove ancient codec

This was used by MSN messenger in prehistoric times, it's safe
to say no one needs or wants this any more these days. For
decoding old recordings there's still a decoder in ffmpeg.

https://bugzilla.gnome.org/show_bug.cgi?id=597616
This commit is contained in:
Tim-Philipp Müller 2016-11-23 10:31:29 +00:00
parent 43736e5c37
commit ad661999ad
17 changed files with 2 additions and 1315 deletions

View file

@ -84,6 +84,7 @@ CRUFT_FILES = \
$(top_builddir)/tests/check/elements/selector \
$(top_builddir)/tests/check/elements/valve \
$(top_builddir)/tests/check/pipelines/metadata \
$(top_builddir)/tests/check/pipelines/mimic \
$(top_builddir)/tests/examples/jack/jack_client \
$(top_builddir)/tests/examples/scaletempo/scaletempo-demo \
$(top_builddir)/tests/examples/switch/switcher \
@ -125,6 +126,7 @@ CRUFT_DIRS = \
$(top_srcdir)/ext/ivorbis \
$(top_srcdir)/ext/jack \
$(top_srcdir)/ext/metadata \
$(top_srcdir)/ext/mimic \
$(top_srcdir)/ext/mpg123 \
$(top_srcdir)/ext/swfdec \
$(top_srcdir)/ext/tarkin \

View file

@ -2547,16 +2547,6 @@ AG_GST_CHECK_FEATURE(MODPLUG, modplug, modplug, [
AC_SUBST(MODPLUG_LIBS)
])
dnl *** mimic ***
translit(dnm, m, l) AM_CONDITIONAL(USE_MIMIC, true)
AG_GST_CHECK_FEATURE(MIMIC, [libmimic library], mimic, [
MIMIC_REQUIRED=1.0
PKG_CHECK_MODULES(MIMIC, libmimic >= $MIMIC_REQUIRED,
HAVE_MIMIC=yes, HAVE_MIMIC=no)
AC_SUBST(MIMIC_CFLAGS)
AC_SUBST(MIMIC_LIBS)
])
dnl *** mjpegtools version info ***
dnl some may prefer older version (given quirks above)
dnl hm, no version info seems available within mjpegtools headers
@ -3550,7 +3540,6 @@ AM_CONDITIONAL(USE_LIBDE265, false)
AM_CONDITIONAL(USE_LIBMMS, false)
AM_CONDITIONAL(USE_LINSYS, false)
AM_CONDITIONAL(USE_MODPLUG, false)
AM_CONDITIONAL(USE_MIMIC, false)
AM_CONDITIONAL(USE_MPEG2ENC, false)
AM_CONDITIONAL(USE_MPLEX, false)
AM_CONDITIONAL(USE_MUSEPACK, false)
@ -3871,7 +3860,6 @@ ext/libvisual/Makefile
ext/Makefile
ext/modplug/Makefile
ext/mpeg2enc/Makefile
ext/mimic/Makefile
ext/mplex/Makefile
ext/musepack/Makefile
ext/nas/Makefile

View file

@ -82,8 +82,6 @@ EXTRA_HFILES = \
$(top_srcdir)/ext/kate/gstkatetag.h \
$(top_srcdir)/ext/kate/gstkatetiger.h \
$(top_srcdir)/ext/ladspa/gstladspa.h \
$(top_srcdir)/ext/mimic/gstmimenc.h \
$(top_srcdir)/ext/mimic/gstmimdec.h \
$(top_srcdir)/ext/modplug/gstmodplug.h \
$(top_srcdir)/ext/mpeg2enc/gstmpeg2enc.hh \
$(top_srcdir)/ext/mplex/gstmplex.hh \

View file

@ -182,7 +182,6 @@
<xi:include href="xml/plugin-geometrictransform.xml" />
<xi:include href="xml/plugin-gsm.xml" />
<xi:include href="xml/plugin-jpegformat.xml" />
<xi:include href="xml/plugin-mimic.xml" />
<xi:include href="xml/plugin-mms.xml" />
<xi:include href="xml/plugin-modplug.xml" />
<xi:include href="xml/plugin-mpeg2enc.xml" />

View file

@ -1,55 +0,0 @@
<plugin>
<name>mimic</name>
<description>Mimic codec</description>
<filename>../../ext/mimic/.libs/libgstmimic.so</filename>
<basename>libgstmimic.so</basename>
<version>1.10.0</version>
<license>LGPL</license>
<source>gst-plugins-bad</source>
<package>GStreamer Bad Plug-ins source release</package>
<origin>Unknown package origin</origin>
<elements>
<element>
<name>mimdec</name>
<longname>Mimic Decoder</longname>
<class>Codec/Decoder/Video</class>
<description>MSN Messenger compatible Mimic video decoder element</description>
<author>Andre Moreira Magalhaes &lt;andre.magalhaes@indt.org.br&gt;, Rob Taylor &lt;robtaylor@fastmail.fm&gt;, Philippe Khalaf &lt;burger@speedy.org&gt;, Ole André Vadla Ravnås &lt;oleavr@gmail.com&gt;,Olivier Crête &lt;olivier.crete@collabora.co.uk</author>
<pads>
<caps>
<name>sink</name>
<direction>sink</direction>
<presence>always</presence>
<details>video/x-mimic</details>
</caps>
<caps>
<name>src</name>
<direction>source</direction>
<presence>always</presence>
<details>video/x-raw, format=(string)RGB, framerate=(fraction)0/1, width=(int)320, height=(int)240; video/x-raw, format=(string)RGB, framerate=(fraction)0/1, width=(int)160, height=(int)120</details>
</caps>
</pads>
</element>
<element>
<name>mimenc</name>
<longname>Mimic Encoder</longname>
<class>Codec/Encoder/Video</class>
<description>MSN Messenger compatible Mimic video encoder element</description>
<author>Andre Moreira Magalhaes &lt;andre.magalhaes@indt.org.br&gt;,Olivier Crête &lt;olivier.crete@collabora.co.uk</author>
<pads>
<caps>
<name>sink</name>
<direction>sink</direction>
<presence>always</presence>
<details>video/x-raw, format=(string)RGB, framerate=(fraction)[ 1/1, 30/1 ], width=(int)320, height=(int)240; video/x-raw, format=(string)RGB, framerate=(fraction)[ 1/1, 30/1 ], width=(int)160, height=(int)120</details>
</caps>
<caps>
<name>src</name>
<direction>source</direction>
<presence>always</presence>
<details>video/x-mimic</details>
</caps>
</pads>
</element>
</elements>
</plugin>

View file

@ -196,12 +196,6 @@ else
MPEG2ENC_DIR=
endif
if USE_MIMIC
MIMIC_DIR=mimic
else
MIMIC_DIR=
endif
if USE_MPLEX
MPLEX_DIR=mplex
else
@ -472,7 +466,6 @@ SUBDIRS=\
$(LIBVISUAL_DIR) \
$(MODPLUG_DIR) \
$(MPEG2ENC_DIR) \
$(MIMIC_DIR) \
$(MPLEX_DIR) \
$(MUSEPACK_DIR) \
$(NAS_DIR) \
@ -542,7 +535,6 @@ DIST_SUBDIRS = \
gtk \
qt \
modplug \
mimic \
mpeg2enc \
mplex \
musepack \

View file

@ -27,7 +27,6 @@ subdir('libde265')
subdir('libmms')
#subdir('libvisual')
#subdir('lv2')
#subdir('mimic')
#subdir('modplug')
#subdir('mpeg2enc')
#subdir('mplex')

View file

@ -1,10 +0,0 @@
plugin_LTLIBRARIES = libgstmimic.la
libgstmimic_la_SOURCES = gstmimic.c gstmimdec.c gstmimenc.c
libgstmimic_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(MIMIC_CFLAGS)
libgstmimic_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(MIMIC_LIBS)
libgstmimic_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstmimic_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
noinst_HEADERS = gstmimdec.h gstmimenc.h

View file

@ -1,366 +0,0 @@
/*
* GStreamer
* Copyright (c) 2005 INdT.
* @author Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>
* @author Rob Taylor <robtaylor@fastmail.fm>
* @author Philippe Khalaf <burger@speedy.org>
* @author Ole André Vadla Ravnås <oleavr@gmail.com>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/**
* SECTION:element-mimdec
* @see_also: mimenc
*
* The MIMIC codec is used by MSN Messenger's webcam support. It consumes the
* TCP header for the MIMIC codec.
*
* Its fourcc is ML20.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include "gstmimdec.h"
GST_DEBUG_CATEGORY (mimdec_debug);
#define GST_CAT_DEFAULT (mimdec_debug)
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-mimic")
);
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw, format= (string) \"RGB\", "
"framerate = (fraction) 0/1, width = (int) 320, height = (int) 240;"
"video/x-raw, format= (string) \"RGB\", "
"framerate = (fraction) 0/1, width = (int) 160, height = (int) 120")
);
static void gst_mim_dec_finalize (GObject * object);
static GstFlowReturn gst_mim_dec_chain (GstPad * pad, GstObject * parent,
GstBuffer * in);
static GstStateChangeReturn
gst_mim_dec_change_state (GstElement * element, GstStateChange transition);
static gboolean gst_mim_dec_sink_event (GstPad * pad, GstObject * parent,
GstEvent * event);
G_DEFINE_TYPE (GstMimDec, gst_mim_dec, GST_TYPE_ELEMENT);
static void
gst_mim_dec_class_init (GstMimDecClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_mim_dec_change_state);
gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
gst_element_class_add_static_pad_template (gstelement_class, &sink_factory);
gst_element_class_set_static_metadata (gstelement_class,
"Mimic Decoder",
"Codec/Decoder/Video",
"MSN Messenger compatible Mimic video decoder element",
"Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>, "
"Rob Taylor <robtaylor@fastmail.fm>, "
"Philippe Khalaf <burger@speedy.org>, "
"Ole André Vadla Ravnås <oleavr@gmail.com>,"
"Olivier Crête <olivier.crete@collabora.co.uk");
gobject_class->finalize = gst_mim_dec_finalize;
GST_DEBUG_CATEGORY_INIT (mimdec_debug, "mimdec", 0, "Mimic decoder plugin");
}
static void
gst_mim_dec_init (GstMimDec * mimdec)
{
mimdec->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
gst_pad_use_fixed_caps (mimdec->sinkpad);
gst_pad_set_chain_function (mimdec->sinkpad,
GST_DEBUG_FUNCPTR (gst_mim_dec_chain));
gst_pad_set_event_function (mimdec->sinkpad,
GST_DEBUG_FUNCPTR (gst_mim_dec_sink_event));
gst_element_add_pad (GST_ELEMENT (mimdec), mimdec->sinkpad);
mimdec->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
gst_pad_use_fixed_caps (mimdec->srcpad);
gst_element_add_pad (GST_ELEMENT (mimdec), mimdec->srcpad);
mimdec->adapter = gst_adapter_new ();
mimdec->dec = NULL;
mimdec->buffer_size = -1;
}
static void
gst_mim_dec_finalize (GObject * object)
{
GstMimDec *mimdec = GST_MIM_DEC (object);
gst_adapter_clear (mimdec->adapter);
g_object_unref (mimdec->adapter);
G_OBJECT_CLASS (gst_mim_dec_parent_class)->finalize (object);
}
static GstFlowReturn
gst_mim_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
GstMimDec *mimdec = GST_MIM_DEC (parent);
GstBuffer *out_buf;
const guchar *header, *frame_body;
guint32 fourcc;
guint16 header_size;
gint width, height;
GstCaps *caps;
GstFlowReturn res = GST_FLOW_OK;
GstClockTime in_time = GST_BUFFER_TIMESTAMP (buf);
GstEvent *event = NULL;
gboolean result = TRUE;
guint32 payload_size;
guint32 current_ts;
GstMapInfo map;
gst_adapter_push (mimdec->adapter, buf);
/* do we have enough bytes to read a header */
while (gst_adapter_available (mimdec->adapter) >= 24) {
header = gst_adapter_map (mimdec->adapter, 24);
header_size = header[0];
if (header_size != 24) {
gst_adapter_unmap (mimdec->adapter);
gst_adapter_flush (mimdec->adapter, 24);
GST_ELEMENT_ERROR (mimdec, STREAM, DECODE, (NULL),
("invalid frame: header size %d incorrect", header_size));
return GST_FLOW_ERROR;
}
if (header[1] == 1) {
/* This is a a paused frame, skip it */
gst_adapter_unmap (mimdec->adapter);
gst_adapter_flush (mimdec->adapter, 24);
continue;
}
fourcc = GUINT32_FROM_LE (*((guint32 *) (header + 12)));
if (GST_MAKE_FOURCC ('M', 'L', '2', '0') != fourcc) {
gst_adapter_unmap (mimdec->adapter);
gst_adapter_flush (mimdec->adapter, 24);
GST_ELEMENT_ERROR (mimdec, STREAM, WRONG_TYPE, (NULL),
("invalid frame: unknown FOURCC code 0x%" G_GINT32_MODIFIER "x",
fourcc));
return GST_FLOW_ERROR;
}
payload_size = GUINT32_FROM_LE (*((guint32 *) (header + 8)));
current_ts = GUINT32_FROM_LE (*((guint32 *) (header + 20)));
gst_adapter_unmap (mimdec->adapter);
GST_LOG_OBJECT (mimdec, "Got packet, payload size %d", payload_size);
if (gst_adapter_available (mimdec->adapter) < payload_size + 24)
return GST_FLOW_OK;
/* We have a whole packet and have read the header, lets flush it out */
gst_adapter_flush (mimdec->adapter, 24);
frame_body = gst_adapter_map (mimdec->adapter, payload_size);
if (mimdec->buffer_size < 0) {
/* Check if its a keyframe, otherwise skip it */
if (GUINT32_FROM_LE (*((guint32 *) (frame_body + 12))) != 0) {
gst_adapter_unmap (mimdec->adapter);
gst_adapter_flush (mimdec->adapter, payload_size);
return GST_FLOW_OK;
}
if (!mimic_decoder_init (mimdec->dec, frame_body)) {
gst_adapter_unmap (mimdec->adapter);
gst_adapter_flush (mimdec->adapter, payload_size);
GST_ELEMENT_ERROR (mimdec, LIBRARY, INIT, (NULL),
("mimic_decoder_init error"));
return GST_FLOW_ERROR;
}
if (!mimic_get_property (mimdec->dec, "buffer_size",
&mimdec->buffer_size)) {
gst_adapter_unmap (mimdec->adapter);
gst_adapter_flush (mimdec->adapter, payload_size);
GST_ELEMENT_ERROR (mimdec, LIBRARY, INIT, (NULL),
("mimic_get_property('buffer_size') error"));
return GST_FLOW_ERROR;
}
mimic_get_property (mimdec->dec, "width", &width);
mimic_get_property (mimdec->dec, "height", &height);
GST_DEBUG_OBJECT (mimdec,
"Initialised decoder with %d x %d payload size %d buffer_size %d",
width, height, payload_size, mimdec->buffer_size);
caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "RGB",
"framerate", GST_TYPE_FRACTION, 0, 1,
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
gst_pad_set_caps (mimdec->srcpad, caps);
gst_caps_unref (caps);
}
if (mimdec->need_segment) {
GstSegment segment;
gst_segment_init (&segment, GST_FORMAT_TIME);
if (GST_CLOCK_TIME_IS_VALID (in_time))
segment.start = in_time;
else
segment.start = current_ts * GST_MSECOND;
event = gst_event_new_segment (&segment);
}
mimdec->need_segment = FALSE;
if (event)
result = gst_pad_push_event (mimdec->srcpad, event);
event = NULL;
if (!result) {
GST_WARNING_OBJECT (mimdec, "gst_pad_push_event failed");
return GST_FLOW_ERROR;
}
out_buf = gst_buffer_new_allocate (NULL, mimdec->buffer_size, NULL);
gst_buffer_map (out_buf, &map, GST_MAP_READWRITE);
if (!mimic_decode_frame (mimdec->dec, frame_body, map.data)) {
GST_WARNING_OBJECT (mimdec, "mimic_decode_frame error\n");
gst_adapter_flush (mimdec->adapter, payload_size);
gst_buffer_unmap (out_buf, &map);
gst_buffer_unref (out_buf);
GST_ELEMENT_ERROR (mimdec, STREAM, DECODE, (NULL),
("mimic_decode_frame error"));
return GST_FLOW_ERROR;
}
gst_buffer_unmap (out_buf, &map);
gst_adapter_flush (mimdec->adapter, payload_size);
if (GST_CLOCK_TIME_IS_VALID (in_time))
GST_BUFFER_TIMESTAMP (out_buf) = in_time;
else
GST_BUFFER_TIMESTAMP (out_buf) = current_ts * GST_MSECOND;
res = gst_pad_push (mimdec->srcpad, out_buf);
if (res != GST_FLOW_OK)
break;
}
return res;
}
static GstStateChangeReturn
gst_mim_dec_change_state (GstElement * element, GstStateChange transition)
{
GstMimDec *mimdec;
GstStateChangeReturn ret;
mimdec = GST_MIM_DEC (element);
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
mimdec->buffer_size = -1;
mimdec->dec = mimic_open ();
if (!mimdec->dec) {
GST_ERROR_OBJECT (mimdec, "mimic_open failed");
return GST_STATE_CHANGE_FAILURE;
}
mimdec->need_segment = TRUE;
gst_adapter_clear (mimdec->adapter);
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (gst_mim_dec_parent_class)->change_state (element,
transition);
if (ret == GST_STATE_CHANGE_FAILURE)
return ret;
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
if (mimdec->dec != NULL) {
mimic_close (mimdec->dec);
mimdec->dec = NULL;
}
break;
default:
break;
}
return ret;
}
static gboolean
gst_mim_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
gboolean res = TRUE;
gboolean forward = TRUE;
GstMimDec *mimdec = GST_MIM_DEC (parent);
/*
* Ignore upstream segment event, its EVIL, we should implement
* proper seeking instead
*/
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEGMENT:
forward = FALSE;
break;
case GST_EVENT_STREAM_START:
case GST_EVENT_FLUSH_STOP:
case GST_EVENT_EOS:
gst_adapter_clear (mimdec->adapter);
break;
default:
break;
}
if (forward)
res = gst_pad_event_default (pad, parent, event);
else
gst_event_unref (event);
return res;
}

View file

@ -1,65 +0,0 @@
/*
* GStreamer
* Copyright (c) 2005 INdT.
* @author Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>
* @author Philippe Khalaf <burger@speedy.org>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_MIM_DEC_H__
#define __GST_MIM_DEC_H__
#include <gst/gst.h>
#include <gst/base/gstadapter.h>
#include <mimic.h>
G_BEGIN_DECLS
#define GST_TYPE_MIM_DEC \
(gst_mim_dec_get_type())
#define GST_MIM_DEC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MIM_DEC,GstMimDec))
#define GST_MIM_DEC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MIM_DEC,GstMimDecClass))
#define GST_IS_MIM_DEC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MIM_DEC))
#define GST_IS_MIM_DEC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MIM_DEC))
typedef struct _GstMimDec GstMimDec;
typedef struct _GstMimDecClass GstMimDecClass;
struct _GstMimDec
{
GstElement element;
GstPad *sinkpad, *srcpad;
/* Protected by stream lock */
GstAdapter *adapter;
MimCtx *dec;
gint buffer_size;
gboolean need_segment;
};
struct _GstMimDecClass
{
GstElementClass parent_class;
};
GType gst_mim_dec_get_type (void);
G_END_DECLS
#endif /* __GST_MIM_DEC_H__ */

View file

@ -1,586 +0,0 @@
/*
* GStreamer
* Copyright (c) 2005 INdT.
* Copyright (c) 2009 Collabora Ltd.
* @author Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>
* @author Philippe Khalaf <burger@speedy.org>
* @author Olivier Crête <olivier.crete@collabora.co.uk>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/**
* SECTION:element-mimenc
* @see_also: mimdec
*
* The MIMIC codec is used by MSN Messenger's webcam support. It creates the
* TCP header for the MIMIC codec.
*
* When using it to communicate directly with MSN Messenger, if the sender
* wants to stop sending, he has to send a special buffer every 4 seconds.
* When the "paused-mode" property is set to TRUE, if the element receives no
* buffer on its sink pad for 4 seconds, it will produced a special paused
* frame and will continue doing so every 4 seconds until a new buffer is
*u received on its sink pad.
*
* Its fourcc is ML20.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include "gstmimenc.h"
GST_DEBUG_CATEGORY (mimenc_debug);
#define GST_CAT_DEFAULT (mimenc_debug)
#define MAX_INTERFRAMES 15
#define TCP_HEADER_SIZE 24
#define PAUSED_MODE_INTERVAL (4 * GST_SECOND)
enum
{
PROP_0,
PROP_PAUSED_MODE,
PROP_LAST
};
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw, format = (string) \"RGB\", "
"framerate = (fraction) [1/1, 30/1], "
"width = (int) 320, "
"height = (int) 240;"
"video/x-raw, format = (string) \"RGB\", "
"framerate = (fraction) [1/1, 30/1], "
"width = (int) 160, " "height = (int) 120")
);
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-mimic")
);
static gboolean gst_mim_enc_setcaps (GstMimEnc * mimenc, GstCaps * caps);
static GstFlowReturn gst_mim_enc_chain (GstPad * pad, GstObject * parent,
GstBuffer * in);
static void gst_mim_enc_create_tcp_header (GstMimEnc * mimenc, guint8 * p,
guint32 payload_size, GstClockTime ts, gboolean keyframe, gboolean paused);
static gboolean gst_mim_enc_event (GstPad * pad, GstObject * parent,
GstEvent * event);
static GstStateChangeReturn
gst_mim_enc_change_state (GstElement * element, GstStateChange transition);
static void gst_mim_enc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_mim_enc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
G_DEFINE_TYPE (GstMimEnc, gst_mim_enc, GST_TYPE_ELEMENT);
static void
gst_mim_enc_class_init (GstMimEncClass * klass)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gst_mim_enc_set_property;
gobject_class->get_property = gst_mim_enc_get_property;
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_mim_enc_change_state);
GST_DEBUG_CATEGORY_INIT (mimenc_debug, "mimenc", 0, "Mimic encoder plugin");
g_object_class_install_property (gobject_class, PROP_PAUSED_MODE,
g_param_spec_boolean ("paused-mode", "Paused mode",
"If enabled, empty frames will be generated every 4 seconds"
" when no data is received",
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
gst_element_class_add_static_pad_template (gstelement_class, &sink_factory);
gst_element_class_set_static_metadata (gstelement_class,
"Mimic Encoder",
"Codec/Encoder/Video",
"MSN Messenger compatible Mimic video encoder element",
"Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>,"
"Olivier Crête <olivier.crete@collabora.co.uk");
}
static void
gst_mim_enc_init (GstMimEnc * mimenc)
{
mimenc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
gst_pad_set_chain_function (mimenc->sinkpad,
GST_DEBUG_FUNCPTR (gst_mim_enc_chain));
gst_pad_set_event_function (mimenc->sinkpad,
GST_DEBUG_FUNCPTR (gst_mim_enc_event));
gst_element_add_pad (GST_ELEMENT (mimenc), mimenc->sinkpad);
mimenc->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
gst_pad_use_fixed_caps (mimenc->srcpad);
gst_element_add_pad (GST_ELEMENT (mimenc), mimenc->srcpad);
mimenc->enc = NULL;
gst_segment_init (&mimenc->segment, GST_FORMAT_TIME);
mimenc->res = MIMIC_RES_HIGH;
mimenc->buffer_size = -1;
mimenc->width = 0;
mimenc->height = 0;
mimenc->frames = 0;
}
static void
gst_mim_enc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstMimEnc *mimenc = GST_MIM_ENC (object);
switch (prop_id) {
case PROP_PAUSED_MODE:
GST_OBJECT_LOCK (mimenc);
mimenc->paused_mode = g_value_get_boolean (value);
if (GST_STATE (object) == GST_STATE_PLAYING)
GST_WARNING_OBJECT (object, "Tried to disable paused-mode in a playing"
" encoder, it will not be stopped until it is paused");
GST_OBJECT_UNLOCK (mimenc);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_mim_enc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstMimEnc *mimenc = GST_MIM_ENC (object);
switch (prop_id) {
case PROP_PAUSED_MODE:
GST_OBJECT_LOCK (mimenc);
g_value_set_boolean (value, mimenc->paused_mode);
GST_OBJECT_UNLOCK (mimenc);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_mim_enc_reset_locked (GstMimEnc * mimenc)
{
if (mimenc->enc != NULL) {
mimic_close (mimenc->enc);
mimenc->enc = NULL;
mimenc->buffer_size = -1;
mimenc->frames = 0;
mimenc->width = 0;
mimenc->height = 0;
}
gst_event_replace (&mimenc->pending_segment, NULL);
}
static void
gst_mim_enc_reset (GstMimEnc * mimenc)
{
GST_OBJECT_LOCK (mimenc);
gst_mim_enc_reset_locked (mimenc);
GST_OBJECT_UNLOCK (mimenc);
}
static gboolean
gst_mim_enc_setcaps (GstMimEnc * mimenc, GstCaps * caps)
{
GstStructure *structure;
int height, width;
gboolean ret = FALSE;
structure = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (structure, "width", &width)) {
GST_DEBUG_OBJECT (mimenc, "No width set");
return FALSE;
}
if (!gst_structure_get_int (structure, "height", &height)) {
GST_DEBUG_OBJECT (mimenc, "No height set");
return FALSE;
}
GST_OBJECT_LOCK (mimenc);
if (mimenc->width == width && mimenc->height == height) {
ret = TRUE;
goto out;
}
if (width == 320 && height == 240)
mimenc->res = MIMIC_RES_HIGH;
else if (width == 160 && height == 120)
mimenc->res = MIMIC_RES_LOW;
else {
GST_WARNING_OBJECT (mimenc, "Invalid resolution %dx%d", width, height);
goto out;
}
gst_mim_enc_reset_locked (mimenc);
mimenc->width = (guint16) width;
mimenc->height = (guint16) height;
GST_DEBUG_OBJECT (mimenc, "Got info from caps w : %d, h : %d",
mimenc->width, mimenc->height);
mimenc->enc = mimic_open ();
if (!mimenc->enc) {
GST_ERROR_OBJECT (mimenc, "mimic_open failed");
goto out;
}
if (!mimic_encoder_init (mimenc->enc, mimenc->res)) {
GST_ERROR_OBJECT (mimenc, "mimic_encoder_init error");
goto out;
}
if (!mimic_get_property (mimenc->enc, "buffer_size", &mimenc->buffer_size)) {
GST_ERROR_OBJECT (mimenc, "mimic_get_property(buffer_size) error");
}
ret = TRUE;
out:
GST_OBJECT_UNLOCK (mimenc);
return ret;
}
static GstFlowReturn
gst_mim_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * in)
{
GstMimEnc *mimenc = GST_MIM_ENC (parent);
GstBuffer *out = NULL;
GstMapInfo in_map;
GstMapInfo out_map;
GstFlowReturn res = GST_FLOW_OK;
gboolean keyframe;
gint buffer_size;
GST_OBJECT_LOCK (mimenc);
gst_buffer_map (in, &in_map, GST_MAP_READ);
out = gst_buffer_new_and_alloc (mimenc->buffer_size + TCP_HEADER_SIZE);
gst_buffer_map (out, &out_map, GST_MAP_READWRITE);
GST_BUFFER_TIMESTAMP (out) =
gst_segment_to_running_time (&mimenc->segment, GST_FORMAT_TIME,
GST_BUFFER_TIMESTAMP (in));
mimenc->last_buffer = GST_BUFFER_TIMESTAMP (out);
buffer_size = mimenc->buffer_size;
keyframe = (mimenc->frames % MAX_INTERFRAMES) == 0 ? TRUE : FALSE;
if (!mimic_encode_frame (mimenc->enc, in_map.data,
out_map.data + TCP_HEADER_SIZE, &buffer_size, keyframe)) {
gst_buffer_unmap (in, &in_map);
gst_buffer_unmap (out, &out_map);
gst_buffer_unref (out);
GST_ELEMENT_ERROR (mimenc, STREAM, ENCODE, (NULL),
("mimic_encode_frame error"));
res = GST_FLOW_ERROR;
goto out_unlock;
}
gst_buffer_unmap (in, &in_map);
if (!keyframe)
GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DELTA_UNIT);
GST_LOG_OBJECT (mimenc, "incoming buf size %" G_GSIZE_FORMAT
", encoded size %" G_GSIZE_FORMAT, gst_buffer_get_size (in),
gst_buffer_get_size (out));
++mimenc->frames;
/* now let's create that tcp header */
gst_mim_enc_create_tcp_header (mimenc, out_map.data, buffer_size,
GST_BUFFER_TIMESTAMP (out), keyframe, FALSE);
gst_buffer_unmap (out, &out_map);
gst_buffer_resize (out, 0, buffer_size + TCP_HEADER_SIZE);
if (G_UNLIKELY (mimenc->pending_segment)) {
gst_pad_push_event (mimenc->srcpad, mimenc->pending_segment);
mimenc->pending_segment = FALSE;
}
GST_OBJECT_UNLOCK (mimenc);
res = gst_pad_push (mimenc->srcpad, out);
out:
gst_buffer_unref (in);
return res;
out_unlock:
GST_OBJECT_UNLOCK (mimenc);
goto out;
}
static void
gst_mim_enc_create_tcp_header (GstMimEnc * mimenc, guint8 * p,
guint32 payload_size, GstClockTime ts, gboolean keyframe, gboolean paused)
{
p[0] = 24;
p[1] = paused ? 1 : 0;
GST_WRITE_UINT16_LE (p + 2, mimenc->width);
GST_WRITE_UINT16_LE (p + 4, mimenc->height);
GST_WRITE_UINT16_LE (p + 6, keyframe ? 1 : 0);
GST_WRITE_UINT32_LE (p + 8, payload_size);
GST_WRITE_UINT32_LE (p + 12, paused ? 0 :
GST_MAKE_FOURCC ('M', 'L', '2', '0'));
GST_WRITE_UINT32_LE (p + 16, 0);
GST_WRITE_UINT32_LE (p + 20, ts / GST_MSECOND);
}
static gboolean
gst_mim_enc_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstMimEnc *mimenc = GST_MIM_ENC (parent);
gboolean ret = TRUE;
gboolean forward = TRUE;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP:
gst_segment_init (&mimenc->segment, GST_FORMAT_UNDEFINED);
gst_event_replace (&mimenc->pending_segment, NULL);
break;
case GST_EVENT_EOS:
gst_mim_enc_reset (mimenc);
break;
case GST_EVENT_CAPS:
{
GstCaps *caps;
gst_event_parse_caps (event, &caps);
ret = gst_mim_enc_setcaps (mimenc, caps);
forward = FALSE;
break;
}
case GST_EVENT_SEGMENT:
{
gst_event_copy_segment (event, &mimenc->segment);
/* we need time for now */
if (mimenc->segment.format != GST_FORMAT_TIME)
goto newseg_wrong_format;
gst_event_replace (&mimenc->pending_segment, event);
forward = FALSE;
break;
}
break;
default:
break;
}
if (forward)
ret = gst_pad_event_default (pad, parent, event);
else
gst_event_unref (event);
done:
return ret;
newseg_wrong_format:
{
GST_DEBUG_OBJECT (mimenc, "received non TIME newsegment");
gst_event_unref (event);
ret = FALSE;
goto done;
}
}
static void
paused_mode_task (gpointer data)
{
GstMimEnc *mimenc = GST_MIM_ENC (data);
GstClockTime now;
GstClockTimeDiff diff;
GstFlowReturn ret;
GST_OBJECT_LOCK (mimenc);
if (!GST_ELEMENT_CLOCK (mimenc)) {
GST_OBJECT_UNLOCK (mimenc);
GST_ERROR_OBJECT (mimenc, "Element has no clock");
gst_pad_pause_task (mimenc->srcpad);
return;
}
if (mimenc->stop_paused_mode) {
GST_OBJECT_UNLOCK (mimenc);
goto stop_task;
}
now = gst_clock_get_time (GST_ELEMENT_CLOCK (mimenc));
diff = now - GST_ELEMENT_CAST (mimenc)->base_time - mimenc->last_buffer;
if (diff < 0)
diff = 0;
if (diff > 3.95 * GST_SECOND) {
GstBuffer *buffer;
GstMapInfo out_map;
buffer = gst_buffer_new_and_alloc (TCP_HEADER_SIZE);
gst_buffer_map (buffer, &out_map, GST_MAP_WRITE);
GST_BUFFER_TIMESTAMP (buffer) = mimenc->last_buffer + PAUSED_MODE_INTERVAL;
gst_mim_enc_create_tcp_header (mimenc, out_map.data, 0,
GST_BUFFER_TIMESTAMP (buffer), FALSE, TRUE);
gst_buffer_unmap (buffer, &out_map);
mimenc->last_buffer += PAUSED_MODE_INTERVAL;
GST_OBJECT_UNLOCK (mimenc);
GST_LOG_OBJECT (mimenc, "Haven't had an incoming buffer in 4 seconds,"
" sending out a pause frame");
ret = gst_pad_push (mimenc->srcpad, buffer);
if (ret < 0) {
GST_WARNING_OBJECT (mimenc, "Error pushing paused header: %s",
gst_flow_get_name (ret));
goto stop_task;
}
} else {
GstClockTime next_stop;
GstClockID id;
next_stop = now + (PAUSED_MODE_INTERVAL - MIN (diff, PAUSED_MODE_INTERVAL));
id = gst_clock_new_single_shot_id (GST_ELEMENT_CLOCK (mimenc), next_stop);
if (mimenc->stop_paused_mode) {
GST_OBJECT_UNLOCK (mimenc);
goto stop_task;
}
mimenc->clock_id = id;
GST_OBJECT_UNLOCK (mimenc);
gst_clock_id_wait (id, NULL);
GST_OBJECT_LOCK (mimenc);
mimenc->clock_id = NULL;
GST_OBJECT_UNLOCK (mimenc);
gst_clock_id_unref (id);
}
return;
stop_task:
gst_pad_pause_task (mimenc->srcpad);
}
static GstStateChangeReturn
gst_mim_enc_change_state (GstElement * element, GstStateChange transition)
{
GstMimEnc *mimenc = GST_MIM_ENC (element);
GstStateChangeReturn ret;
gboolean paused_mode;
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
GST_OBJECT_LOCK (mimenc);
gst_segment_init (&mimenc->segment, GST_FORMAT_UNDEFINED);
gst_event_replace (&mimenc->pending_segment, NULL);
mimenc->last_buffer = GST_CLOCK_TIME_NONE;
GST_OBJECT_UNLOCK (mimenc);
break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
GST_OBJECT_LOCK (mimenc);
if (mimenc->clock_id)
gst_clock_id_unschedule (mimenc->clock_id);
mimenc->stop_paused_mode = TRUE;
GST_OBJECT_UNLOCK (mimenc);
gst_pad_pause_task (mimenc->srcpad);
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (gst_mim_enc_parent_class)->change_state (element,
transition);
if (ret == GST_STATE_CHANGE_FAILURE)
return ret;
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
GST_OBJECT_LOCK (mimenc);
mimenc->stop_paused_mode = FALSE;
paused_mode = mimenc->paused_mode;
if (paused_mode) {
if (!GST_ELEMENT_CLOCK (mimenc)) {
GST_OBJECT_UNLOCK (mimenc);
GST_ELEMENT_ERROR (mimenc, RESOURCE, FAILED,
("Using paused-mode requires a clock, but no clock was provided"
" to the element"), (NULL));
return GST_STATE_CHANGE_FAILURE;
}
if (mimenc->last_buffer == GST_CLOCK_TIME_NONE)
mimenc->last_buffer = gst_clock_get_time (GST_ELEMENT_CLOCK (mimenc))
- GST_ELEMENT_CAST (mimenc)->base_time;
}
GST_OBJECT_UNLOCK (mimenc);
if (paused_mode) {
if (!gst_pad_start_task (mimenc->srcpad, paused_mode_task, mimenc,
NULL)) {
ret = GST_STATE_CHANGE_FAILURE;
GST_ERROR_OBJECT (mimenc, "Can not start task");
}
}
break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_mim_enc_reset (mimenc);
break;
default:
break;
}
return ret;
}

View file

@ -1,74 +0,0 @@
/*
* GStreamer
* Copyright (c) 2005 INdT.
* @author Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>
* @author Philippe Khalaf <burger@speedy.org>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_MIM_ENC_H__
#define __GST_MIM_ENC_H__
#include <glib.h>
#include <gst/gst.h>
#include <mimic.h>
G_BEGIN_DECLS
#define GST_TYPE_MIM_ENC \
(gst_mim_enc_get_type())
#define GST_MIM_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MIM_ENC,GstMimEnc))
#define GST_MIM_ENC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MIM_ENC,GstMimEncClass))
#define GST_IS_MIM_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MIM_ENC))
#define GST_IS_MIM_ENC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MIM_ENC))
typedef struct _GstMimEnc GstMimEnc;
typedef struct _GstMimEncClass GstMimEncClass;
struct _GstMimEnc
{
GstElement element;
GstPad *sinkpad, *srcpad;
/* Protected by the object lock */
MimCtx *enc;
MimicResEnum res;
gint buffer_size;
guint32 frames;
guint16 height, width;
gboolean paused_mode;
GstSegment segment;
GstEvent *pending_segment;
GstClockTime last_buffer;
GstClockID clock_id;
gboolean stop_paused_mode;
};
struct _GstMimEncClass
{
GstElementClass parent_class;
};
GType gst_mim_enc_get_type (void);
G_END_DECLS
#endif /* __GST_MIM_ENC_H__ */

View file

@ -1,46 +0,0 @@
/*
* GStreamer
* Copyright (c) 2005 INdT.
* @author Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>
* @author Philippe Khalaf <burger@speedy.org>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstmimenc.h"
#include "gstmimdec.h"
static gboolean
plugin_init (GstPlugin * plugin)
{
if (!gst_element_register (plugin, "mimenc", GST_RANK_NONE,
GST_TYPE_MIM_ENC) ||
!gst_element_register (plugin, "mimdec", GST_RANK_NONE, GST_TYPE_MIM_DEC)
)
return FALSE;
return TRUE;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
mimic,
"Mimic codec",
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

View file

@ -59,7 +59,6 @@ BuildRequires: xvidcore-devel
BuildRequires: libmms-devel
BuildRequires: mjpegtools-devel
BuildRequires: twolame-devel
BuildRequires: libmimic-devel
Obsoletes: gstreamer-plugins-flumpegdemux < 0.10.15-9
@ -244,7 +243,6 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS=''
%{_libdir}/gstreamer-%{majorminor}/libgstgeometrictransform.so
%{_libdir}/gstreamer-%{majorminor}/libgstid3tag.so
%{_libdir}/gstreamer-%{majorminor}/libgstinterlace.so
%{_libdir}/gstreamer-%{majorminor}/libgstmimic.so
%{_libdir}/gstreamer-%{majorminor}/libgstmpegpsdemux.so
%{_libdir}/gstreamer-%{majorminor}/libgstmpegtsdemux.so
%{_libdir}/gstreamer-%{majorminor}/libgstmpegtsmux.so

View file

@ -132,12 +132,6 @@ else
check_kate=
endif
if USE_MIMIC
check_mimic=pipelines/mimic
else
check_mimic=
endif
if HAVE_ORC
check_orc = orc/bayer orc/audiomixer orc/compositor
else
@ -288,7 +282,6 @@ check_PROGRAMS = \
elements/rtponviftimestamp \
elements/id3mux \
pipelines/mxf \
$(check_mimic) \
libs/mpegvideoparser \
libs/mpegts \
libs/h264parser \

View file

@ -1,6 +1,5 @@
.dirstamp
colorspace
mxf
mimic
tagschecking
streamheader

View file

@ -1,79 +0,0 @@
/* GStreamer
*
* unit test for mimic
*
* Copyright 2009 Collabora Ltd.
* @author: Olivier Crete <olivier.crete@collabora.co.uk>
* Copyright 2009 Nokia Corp.
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <gst/check/gstcheck.h>
static GMainLoop *loop;
static void
eos_message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
{
GST_DEBUG ("Received eos");
g_main_loop_quit (loop);
}
GST_START_TEST (test_mimic_pipeline)
{
GstElement *pipeline;
GError *error = NULL;
GstBus *bus;
const gchar *bin_str = "videotestsrc num-buffers=10 ! mimenc ! "
"mimdec ! fakesink";
pipeline = gst_parse_launch (bin_str, &error);
fail_unless (pipeline != NULL, "Error parsing pipeline: %s", bin_str,
error ? error->message : "(invalid error)");
loop = g_main_loop_new (NULL, FALSE);
bus = gst_element_get_bus (pipeline);
gst_bus_add_signal_watch (bus);
g_signal_connect (bus, "message::eos", (GCallback) eos_message_cb, NULL);
gst_object_unref (bus);
fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING)
!= GST_STATE_CHANGE_FAILURE);
g_main_loop_run (loop);
g_main_loop_unref (loop);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
}
GST_END_TEST;
static Suite *
mimic_suite (void)
{
Suite *s = suite_create ("mimic");
TCase *tc_chain;
tc_chain = tcase_create ("mimic_pipeline");
tcase_add_test (tc_chain, test_mimic_pipeline);
suite_add_tcase (s, tc_chain);
return s;
}
GST_CHECK_MAIN (mimic)