mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
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:
parent
43736e5c37
commit
ad661999ad
17 changed files with 2 additions and 1315 deletions
|
@ -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 \
|
||||
|
|
12
configure.ac
12
configure.ac
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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 <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</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 <andre.magalhaes@indt.org.br>,Olivier Crête <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>
|
|
@ -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 \
|
||||
|
|
|
@ -27,7 +27,6 @@ subdir('libde265')
|
|||
subdir('libmms')
|
||||
#subdir('libvisual')
|
||||
#subdir('lv2')
|
||||
#subdir('mimic')
|
||||
#subdir('modplug')
|
||||
#subdir('mpeg2enc')
|
||||
#subdir('mplex')
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
1
tests/check/pipelines/.gitignore
vendored
1
tests/check/pipelines/.gitignore
vendored
|
@ -1,6 +1,5 @@
|
|||
.dirstamp
|
||||
colorspace
|
||||
mxf
|
||||
mimic
|
||||
tagschecking
|
||||
streamheader
|
||||
|
|
|
@ -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)
|
Loading…
Reference in a new issue