diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2016-12-21 11:00:47 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2016-12-21 11:17:11 +0200 |
commit | 9b5de053995488d5ddc78c1bf4df651101271d70 (patch) | |
tree | 07755463428bf4460852180dc4d3155cc28bf488 /ext | |
parent | 0fdd4e2539cc8c2c794419b13594ed7761d5fccd (diff) | |
download | gstreamer-plugins-bad-9b5de053995488d5ddc78c1bf4df651101271d70.tar.gz |
Remove various unported plugins
If they were not ported after 4+ years it seems unlikely that anybody is
ever going to need them again. They're still in the GIT history if
needed.
https://bugzilla.gnome.org/show_bug.cgi?id=774530
Diffstat (limited to 'ext')
39 files changed, 6 insertions, 10473 deletions
diff --git a/ext/Makefile.am b/ext/Makefile.am index fdce19efe..534b9ac7b 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -10,12 +10,6 @@ else VOAMRWBENC_DIR = endif -if USE_APEXSINK -APEXSINK_DIR = apexsink -else -APEXSINK_DIR = -endif - if USE_BS2B BS2B_DIR=bs2b else @@ -178,12 +172,6 @@ else LIBMMS_DIR= endif -if USE_LIBVISUAL -LIBVISUAL_DIR=libvisual -else -LIBVISUAL_DIR= -endif - if USE_MODPLUG MODPLUG_DIR=modplug else @@ -208,12 +196,6 @@ else MUSEPACK_DIR= endif -if USE_NAS -NAS_DIR=nas -else -NAS_DIR= -endif - if USE_NEON NEON_DIR=neon else @@ -274,18 +256,12 @@ else RSVG_DIR= endif -if USE_TIMIDITY -TIMIDITY_DIR=timidity -endif - if USE_WILDMIDI -TIMIDITY_DIR=timidity +WILDMIDI_DIR=wildmidi endif if !USE_WILDMIDI -if !USE_TIMIDITY -TIMIDITY_DIR= -endif +WILDMIDI_DIR= endif if USE_FLUIDSYNTH @@ -304,12 +280,6 @@ else SCHRO_DIR= endif -if USE_SDL -SDL_DIR=sdl -else -SDL_DIR= -endif - if USE_SMOOTHSTREAMING SMOOTHSTREAMING_DIR = smoothstreaming else @@ -328,12 +298,6 @@ else SNDFILE_DIR= endif -if USE_SNDIO -SNDIO_DIR = sndio -else -SNDIO_DIR = -endif - if USE_SOUNDTOUCH SOUNDTOUCH_DIR=soundtouch else @@ -370,12 +334,6 @@ else TELETEXTDEC_DIR= endif -if USE_XVID -XVID_DIR=xvid -else -XVID_DIR= -endif - if USE_ZBAR ZBAR_DIR=zbar else @@ -434,7 +392,6 @@ SUBDIRS=\ $(VOAACENC_DIR) \ $(ASSRENDER_DIR) \ $(VOAMRWBENC_DIR) \ - $(APEXSINK_DIR) \ $(AUDIOFILE_DIR) \ $(BS2B_DIR) \ $(BZ2_DIR) \ @@ -463,12 +420,10 @@ SUBDIRS=\ $(LV2_DIR) \ $(LIBDE265_DIR) \ $(LIBMMS_DIR) \ - $(LIBVISUAL_DIR) \ $(MODPLUG_DIR) \ $(MPEG2ENC_DIR) \ $(MPLEX_DIR) \ $(MUSEPACK_DIR) \ - $(NAS_DIR) \ $(NEON_DIR) \ $(OFA_DIR) \ $(OPENAL_DIR) \ @@ -481,19 +436,16 @@ SUBDIRS=\ $(RSVG_DIR) \ $(SBC_DIR) \ $(SCHRO_DIR) \ - $(SDL_DIR) \ $(SMOOTHSTREAMING_DIR) \ $(SMOOTHWAVE_DIR) \ $(SNDFILE_DIR) \ - $(SNDIO_DIR) \ $(SOUNDTOUCH_DIR) \ $(SPANDSP_DIR) \ $(GME_DIR) \ $(SPC_DIR) \ $(SRTP_DIR) \ $(TELETEXTDEC_DIR) \ - $(TIMIDITY_DIR) \ - $(XVID_DIR) \ + $(WILDMIDI_DIR) \ $(ZBAR_DIR) \ $(RTMP_DIR) \ $(HLS_DIR) \ @@ -506,7 +458,6 @@ SUBDIRS=\ DIST_SUBDIRS = \ assrender \ - apexsink \ bs2b \ bz2 \ chromaprint \ @@ -527,7 +478,6 @@ DIST_SUBDIRS = \ kate \ libde265 \ libmms \ - libvisual \ lv2 \ daala \ dts \ @@ -538,7 +488,6 @@ DIST_SUBDIRS = \ mpeg2enc \ mplex \ musepack \ - nas \ neon \ ofa \ openal \ @@ -552,20 +501,17 @@ DIST_SUBDIRS = \ resindvd \ sbc \ schroedinger \ - sdl \ smoothstreaming \ sndfile \ - sndio \ soundtouch \ spandsp \ spc \ srtp \ gme \ teletextdec \ - timidity \ + wildmidi \ voaacenc \ voamrwbenc \ - xvid \ zbar \ rtmp \ webp \ diff --git a/ext/apexsink/LGPL-3.0.txt b/ext/apexsink/LGPL-3.0.txt deleted file mode 100644 index fc8a5de7e..000000000 --- a/ext/apexsink/LGPL-3.0.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/ext/apexsink/Makefile.am b/ext/apexsink/Makefile.am deleted file mode 100644 index f799c0794..000000000 --- a/ext/apexsink/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -plugin_LTLIBRARIES = libgstapexsink.la - -libgstapexsink_la_SOURCES = gstapexplugin.c gstapexraop.c gstapexsink.c -libgstapexsink_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(APEXSINK_CFLAGS) -libgstapexsink_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ - -lgstaudio-$(GST_API_VERSION) -lgstinterfaces-$(GST_API_VERSION) \ - $(GST_BASE_LIBS) $(GST_LIBS) $(APEXSINK_LIBS) -libgstapexsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstapexsink_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) - -noinst_HEADERS = gstapexraop.h gstapexsink.h diff --git a/ext/apexsink/gstapexplugin.c b/ext/apexsink/gstapexplugin.c deleted file mode 100644 index a6d64a86b..000000000 --- a/ext/apexsink/gstapexplugin.c +++ /dev/null @@ -1,44 +0,0 @@ -/* GStreamer AirPort Express Plugin - * - * Copyright (C) 2008 Jérémie Bernard [GRemi] <gremimail@gmail.com> - * - * gstapexpugin.c - * - * 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 <gst/gst.h> -#include <gstapexsink.h> - -static gboolean -plugin_init (GstPlugin * plugin) -{ - return gst_element_register (plugin, GST_APEX_SINK_NAME, GST_RANK_NONE, - GST_TYPE_APEX_SINK); -} - -/* plugin export resolution */ -GST_PLUGIN_DEFINE - (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - apexsink, - "Apple AirPort Express Plugin", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/apexsink/gstapexraop.c b/ext/apexsink/gstapexraop.c deleted file mode 100644 index af4f573c0..000000000 --- a/ext/apexsink/gstapexraop.c +++ /dev/null @@ -1,798 +0,0 @@ -/* GStreamer - Remote Audio Access Protocol (RAOP) as used in Apple iTunes to stream music to the Airport Express (ApEx) - - * - * RAOP is based on the Real Time Streaming Protocol (RTSP) but with an extra challenge-response RSA based authentication step. - * This interface accepts RAW PCM data and set it as AES encrypted ALAC while performing emission. - * - * Copyright (C) 2008 Jérémie Bernard [GRemi] <gremimail@gmail.com> - * - * gstapexraop.c - * - * 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 <string.h> - -#include "gstapexraop.h" - -/* private constants */ -#define GST_APEX_RAOP_VOLUME_MIN -144 -#define GST_APEX_RAOP_VOLUME_MAX 0 - -#define GST_APEX_RAOP_HDR_DEFAULT_LENGTH 1024 -#define GST_APEX_RAOP_SDP_DEFAULT_LENGTH 2048 - -const static gchar GST_APEX_RAOP_RSA_PUBLIC_MOD[] = - "59dE8qLieItsH1WgjrcFRKj6eUWqi+bGLOX1HL3U3GhC/j0Qg90u3sG/1CUtwC" - "5vOYvfDmFI6oSFXi5ELabWJmT2dKHzBJKa3k9ok+8t9ucRqMd6DZHJ2YCCLlDR" - "KSKv6kDqnw4UwPdpOMXziC/AMj3Z/lUVX1G7WSHCAWKf1zNS1eLvqr+boEjXuB" - "OitnZ/bDzPHrTOZz0Dew0uowxf/+sG+NCK3eQJVxqcaJ/vEHKIVd2M+5qL71yJ" - "Q+87X6oV3eaYvt3zWZYD6z5vYTcrtij2VZ9Zmni/UAaHqn9JdsBWLUEpVviYnh" - "imNVvYFZeCXg/IdTQ+x4IRdiXNv5hEew=="; - -const static gchar GST_APEX_RAOP_RSA_PUBLIC_EXP[] = "AQAB"; - -const static gchar GST_APEX_RAOP_USER_AGENT[] = - "iTunes/4.6 (Macintosh; U; PPC Mac OS X 10.3)"; - -const static guchar GST_APEX_RAOP_FRAME_HEADER[] = { // Used by gen. 1 - 0x24, 0x00, 0x00, 0x00, - 0xF0, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -const static int GST_APEX_RAOP_FRAME_HEADER_SIZE = 16; // Used by gen. 1 -const static int GST_APEX_RTP_FRAME_HEADER_SIZE = 12; // Used by gen. 2 - -const static int GST_APEX_RAOP_ALAC_HEADER_SIZE = 3; - -/* string extra utility */ -static gint -g_strdel (gchar * str, gchar rc) -{ - int i = 0, j = 0, len, num = 0; - len = strlen (str); - while (i < len) { - if (str[i] == rc) { - for (j = i; j < len; j++) - str[j] = str[j + 1]; - len--; - num++; - } else { - i++; - } - } - return num; -} - -/* socket utilities */ -static int -gst_apexraop_send (int desc, void *data, size_t len) -{ - int total = 0, bytesleft = len, n = 0; - - while (total < len) { - n = send (desc, ((const char *) data) + total, bytesleft, 0); - if (n == -1) - break; - total += n; - bytesleft -= n; - } - - return n == -1 ? -1 : total; -} - -static int -gst_apexraop_recv (int desc, void *data, size_t len) -{ - memset (data, 0, len); - return recv (desc, data, len, 0); -} - -/* public opaque handle resolution */ -typedef struct -{ - guchar aes_ky[AES_BLOCK_SIZE]; /* AES random key */ - guchar aes_iv[AES_BLOCK_SIZE]; /* AES random initial vector */ - - guchar url_abspath[16]; /* header url random absolute path addon, ANNOUNCE id */ - gint cseq; /* header rtsp inc cseq */ - guchar cid[24]; /* header client instance id */ - gchar *session; /* header raop negotiated session id, once SETUP performed */ - gchar *ua; /* header user agent */ - - GstApExJackType jack_type; /* APEX connected jack type, once ANNOUNCE performed */ - GstApExJackStatus jack_status; /* APEX connected jack status, once ANNOUNCE performed */ - - GstApExGeneration generation; /* Different devices accept different audio streams */ - GstApExTransportProtocol transport_protocol; /* For media stream, not RAOP/RTSP */ - - gchar *host; /* APEX target ip */ - guint ctrl_port; /* APEX target control port */ - guint data_port; /* APEX negotiated data port, once SETUP performed */ - - int ctrl_sd; /* control socket */ - struct sockaddr_in ctrl_sd_in; - - int data_sd; /* data socket */ - struct sockaddr_in data_sd_in; - - short rtp_seq_num; /* RTP sequence number, used by gen. 2 */ - int rtp_timestamp; /* RTP timestamp, used by gen. 2 */ -} -_GstApExRAOP; - -/* raop apex struct allocation */ -GstApExRAOP * -gst_apexraop_new (const gchar * host, - const guint16 port, - const GstApExGeneration generation, - const GstApExTransportProtocol transport_protocol) -{ - _GstApExRAOP *apexraop; - - apexraop = (_GstApExRAOP *) g_malloc0 (sizeof (_GstApExRAOP)); - - apexraop->host = g_strdup (host); - apexraop->ctrl_port = port; - apexraop->ua = g_strdup (GST_APEX_RAOP_USER_AGENT); - apexraop->jack_type = GST_APEX_JACK_TYPE_UNDEFINED; - apexraop->jack_status = GST_APEX_JACK_STATUS_DISCONNECTED; - apexraop->generation = generation; - apexraop->transport_protocol = transport_protocol; - apexraop->rtp_seq_num = 0; - apexraop->rtp_timestamp = 0; - - return (GstApExRAOP *) apexraop; -} - -/* raop apex struct freeing */ -void -gst_apexraop_free (GstApExRAOP * con) -{ - _GstApExRAOP *conn; - conn = (_GstApExRAOP *) con; - - g_free (conn->host); - g_free (conn->session); - g_free (conn->ua); - g_free (conn); -} - -/* host affectation */ -void -gst_apexraop_set_host (GstApExRAOP * con, const gchar * host) -{ - _GstApExRAOP *conn; - conn = (_GstApExRAOP *) con; - - g_free (conn->host); - conn->host = g_strdup (host); -} - -/* host reader */ -gchar * -gst_apexraop_get_host (GstApExRAOP * con) -{ - _GstApExRAOP *conn; - conn = (_GstApExRAOP *) con; - - return g_strdup (conn->host); -} - -/* control port affectation */ -void -gst_apexraop_set_port (GstApExRAOP * con, const guint16 port) -{ - _GstApExRAOP *conn; - conn = (_GstApExRAOP *) con; - - conn->ctrl_port = port; -} - -/* control port reader */ -guint16 -gst_apexraop_get_port (GstApExRAOP * con) -{ - _GstApExRAOP *conn; - conn = (_GstApExRAOP *) con; - - return conn->ctrl_port; -} - -/* user agent affectation */ -void -gst_apexraop_set_useragent (GstApExRAOP * con, const gchar * useragent) -{ - _GstApExRAOP *conn; - conn = (_GstApExRAOP *) con; - - g_free (conn->ua); - conn->ua = g_strdup (useragent); -} - -/* user agent reader */ -gchar * -gst_apexraop_get_useragent (GstApExRAOP * con) -{ - _GstApExRAOP *conn; - conn = (_GstApExRAOP *) con; - - return g_strdup (conn->ua); -} - -/* raop apex connection sequence */ -GstRTSPStatusCode -gst_apexraop_connect (GstApExRAOP * con) -{ - gchar *ac, *ky, *iv, *s, inaddr[INET_ADDRSTRLEN], - creq[GST_APEX_RAOP_SDP_DEFAULT_LENGTH], - hreq[GST_APEX_RAOP_HDR_DEFAULT_LENGTH], *req; - RSA *rsa; - guchar *mod, *exp, rsakey[512]; - union gst_randbytes - { - struct asvals - { - guint32 url_key; - guint64 conn_id; - guchar challenge[16]; - } v; - guchar buf[4 + 8 + 16]; - } randbuf; - gsize size; - struct sockaddr_in ioaddr; - socklen_t iolen; - GstRTSPStatusCode res; - _GstApExRAOP *conn; - - conn = (_GstApExRAOP *) con; - - if ((conn->ctrl_sd = socket (AF_INET, SOCK_STREAM, 0)) < 0) - return GST_RTSP_STS_DESTINATION_UNREACHABLE; - - conn->ctrl_sd_in.sin_family = AF_INET; - conn->ctrl_sd_in.sin_port = htons (conn->ctrl_port); - - if (!inet_aton (conn->host, &conn->ctrl_sd_in.sin_addr)) { - struct hostent *hp = (struct hostent *) gethostbyname (conn->host); - if (hp == NULL) - return GST_RTSP_STS_DESTINATION_UNREACHABLE; - memcpy (&conn->ctrl_sd_in.sin_addr, hp->h_addr, hp->h_length); - } - - if (connect (conn->ctrl_sd, (struct sockaddr *) &conn->ctrl_sd_in, - sizeof (conn->ctrl_sd_in)) < 0) - return GST_RTSP_STS_DESTINATION_UNREACHABLE; - - RAND_bytes (randbuf.buf, sizeof (randbuf)); - sprintf ((gchar *) conn->url_abspath, "%u", randbuf.v.url_key); - sprintf ((char *) conn->cid, "%16" G_GINT64_MODIFIER "x", randbuf.v.conn_id); - - RAND_bytes (conn->aes_ky, AES_BLOCK_SIZE); - RAND_bytes (conn->aes_iv, AES_BLOCK_SIZE); - - rsa = RSA_new (); - mod = g_base64_decode (GST_APEX_RAOP_RSA_PUBLIC_MOD, &size); - rsa->n = BN_bin2bn (mod, size, NULL); - exp = g_base64_decode (GST_APEX_RAOP_RSA_PUBLIC_EXP, &size); - rsa->e = BN_bin2bn (exp, size, NULL); - size = - RSA_public_encrypt (AES_BLOCK_SIZE, conn->aes_ky, rsakey, rsa, - RSA_PKCS1_OAEP_PADDING); - - ky = g_base64_encode (rsakey, size); - iv = g_base64_encode (conn->aes_iv, AES_BLOCK_SIZE); - g_strdel (ky, '='); - g_strdel (iv, '='); - - iolen = sizeof (struct sockaddr); - getsockname (conn->ctrl_sd, (struct sockaddr *) &ioaddr, &iolen); - inet_ntop (AF_INET, &(ioaddr.sin_addr), inaddr, INET_ADDRSTRLEN); - - ac = g_base64_encode (randbuf.v.challenge, 16); - g_strdel (ac, '='); - - sprintf (creq, - "v=0\r\n" - "o=iTunes %s 0 IN IP4 %s\r\n" - "s=iTunes\r\n" - "c=IN IP4 %s\r\n" - "t=0 0\r\n" - "m=audio 0 RTP/AVP 96\r\n" - "a=rtpmap:96 AppleLossless\r\n" - "a=fmtp:96 %d 0 %d 40 10 14 %d 255 0 0 %d\r\n" - "a=rsaaeskey:%s\r\n" - "a=aesiv:%s\r\n", - conn->url_abspath, - inaddr, - conn->host, - conn->generation == GST_APEX_GENERATION_ONE - ? GST_APEX_RAOP_V1_SAMPLES_PER_FRAME - : GST_APEX_RAOP_V2_SAMPLES_PER_FRAME, - GST_APEX_RAOP_BYTES_PER_CHANNEL * 8, - GST_APEX_RAOP_CHANNELS, GST_APEX_RAOP_BITRATE, ky, iv); - - sprintf (hreq, - "ANNOUNCE rtsp://%s/%s RTSP/1.0\r\n" - "CSeq: %d\r\n" - "Client-Instance: %s\r\n" - "User-Agent: %s\r\n" - "Content-Type: application/sdp\r\n" - "Content-Length: %u\r\n" - "Apple-Challenge: %s\r\n", - conn->host, - conn->url_abspath, ++conn->cseq, conn->cid, conn->ua, - (guint) strlen (creq), ac); - - RSA_free (rsa); - g_free (ky); - g_free (iv); - g_free (ac); - g_free (mod); - g_free (exp); - - req = g_strconcat (hreq, "\r\n", creq, NULL); - - if (gst_apexraop_send (conn->ctrl_sd, req, strlen (req)) <= 0) { - g_free (req); - return GST_RTSP_STS_GONE; - } - - g_free (req); - - if (gst_apexraop_recv (conn->ctrl_sd, hreq, - GST_APEX_RAOP_HDR_DEFAULT_LENGTH) <= 0) - return GST_RTSP_STS_GONE; - - { - int tmp; - sscanf (hreq, "%*s %d", &tmp); - res = (GstRTSPStatusCode) tmp; - } - - if (res != GST_RTSP_STS_OK) - return res; - - s = g_strrstr (hreq, "Audio-Jack-Status"); - - if (s != NULL) { - gchar status[128]; - sscanf (s, "%*s %s", status); - - if (strcmp (status, "connected;") == 0) - conn->jack_status = GST_APEX_JACK_STATUS_CONNECTED; - else if (strcmp (status, "disconnected;") == 0) - conn->jack_status = GST_APEX_JACK_STATUS_DISCONNECTED; - else - conn->jack_status = GST_APEX_JACK_STATUS_UNDEFINED; - - s = g_strrstr (s, "type="); - - if (s != NULL) { - strtok (s, "="); - s = strtok (NULL, "\n"); - - if (strcmp (s, "analog")) - conn->jack_type = GST_APEX_JACK_TYPE_ANALOG; - else if (strcmp (s, "digital")) - conn->jack_type = GST_APEX_JACK_TYPE_DIGITAL; - else - conn->jack_type = GST_APEX_JACK_TYPE_UNDEFINED; - } - } - - sprintf (hreq, - "SETUP rtsp://%s/%s RTSP/1.0\r\n" - "CSeq: %d\r\n" - "Client-Instance: %s\r\n" - "User-Agent: %s\r\n" - "Transport: RTP/AVP/TCP;unicast;interleaved=0-1;mode=record\r\n" - "\r\n", conn->host, conn->url_abspath, ++conn->cseq, conn->cid, conn->ua); - - if (gst_apexraop_send (conn->ctrl_sd, hreq, strlen (hreq)) <= 0) - return GST_RTSP_STS_GONE; - - if (gst_apexraop_recv (conn->ctrl_sd, hreq, - GST_APEX_RAOP_HDR_DEFAULT_LENGTH) <= 0) - return GST_RTSP_STS_GONE; - - { - int tmp; - sscanf (hreq, "%*s %d", &tmp); - res = (GstRTSPStatusCode) tmp; - } - - if (res != GST_RTSP_STS_OK) - return res; - - s = g_strrstr (hreq, "Session"); - - if (s != NULL) { - gchar session[128]; - sscanf (s, "%*s %s", session); - conn->session = g_strdup (session); - } else - return GST_RTSP_STS_PRECONDITION_FAILED; - - s = g_strrstr (hreq, "server_port"); - if (s != NULL) { - sscanf (s, "server_port=%d", &conn->data_port); - } else - return GST_RTSP_STS_PRECONDITION_FAILED; - - sprintf (hreq, - "RECORD rtsp://%s/%s RTSP/1.0\r\n" - "CSeq: %d\r\n" - "Client-Instance: %s\r\n" - "User-Agent: %s\r\n" - "Session: %s\r\n" - "Range: npt=0-\r\n" - "RTP-Info: seq=0;rtptime=0\r\n" - "\r\n", - conn->host, - conn->url_abspath, ++conn->cseq, conn->cid, conn->ua, conn->session); - - if (gst_apexraop_send (conn->ctrl_sd, hreq, strlen (hreq)) <= 0) - return GST_RTSP_STS_GONE; - - if (gst_apexraop_recv (conn->ctrl_sd, hreq, - GST_APEX_RAOP_HDR_DEFAULT_LENGTH) <= 0) - return GST_RTSP_STS_GONE; - - { - int tmp; - sscanf (hreq, "%*s %d", &tmp); - res = (GstRTSPStatusCode) tmp; - } - - if (res != GST_RTSP_STS_OK) - return res; - - if (conn->transport_protocol == GST_APEX_TCP) { - if ((conn->data_sd = socket (AF_INET, SOCK_STREAM, 0)) < 0) - return GST_RTSP_STS_DESTINATION_UNREACHABLE; - } else if (conn->transport_protocol == GST_APEX_UDP) { - if ((conn->data_sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) - return GST_RTSP_STS_DESTINATION_UNREACHABLE; - } else - return GST_RTSP_STS_METHOD_NOT_ALLOWED; - - conn->data_sd_in.sin_family = AF_INET; - conn->data_sd_in.sin_port = htons (conn->data_port); - - memcpy (&conn->data_sd_in.sin_addr, &conn->ctrl_sd_in.sin_addr, - sizeof (conn->ctrl_sd_in.sin_addr)); - - if (connect (conn->data_sd, (struct sockaddr *) &conn->data_sd_in, - sizeof (conn->data_sd_in)) < 0) - return GST_RTSP_STS_DESTINATION_UNREACHABLE; - - return res; -} - -/* raop apex jack type access */ -GstApExJackType -gst_apexraop_get_jacktype (GstApExRAOP * con) -{ - _GstApExRAOP *conn; - - conn = (_GstApExRAOP *) con; - - if (!conn) - return GST_APEX_JACK_TYPE_UNDEFINED; - - return conn->jack_type; -} - -/* raop apex jack status access */ -GstApExJackStatus -gst_apexraop_get_jackstatus (GstApExRAOP * con) -{ - _GstApExRAOP *conn; - - conn = (_GstApExRAOP *) con; - - if (!conn) - return GST_APEX_JACK_STATUS_UNDEFINED; - - return conn->jack_status; -} - -/* raop apex generation access */ -GstApExGeneration -gst_apexraop_get_generation (GstApExRAOP * con) -{ - _GstApExRAOP *conn; - - conn = (_GstApExRAOP *) con; - - if (!conn) - return GST_APEX_GENERATION_ONE; - - return conn->generation; -} - -/* raop apex transport protocol access */ -GstApExTransportProtocol -gst_apexraop_get_transport_protocol (GstApExRAOP * con) -{ - _GstApExRAOP *conn; - - conn = (_GstApExRAOP *) con; - - if (!conn) - return GST_APEX_TCP; - - return conn->transport_protocol; -} - -/* raop apex sockets close */ -void -gst_apexraop_close (GstApExRAOP * con) -{ - gchar hreq[GST_APEX_RAOP_HDR_DEFAULT_LENGTH]; - _GstApExRAOP *conn; - - conn = (_GstApExRAOP *) con; - - sprintf (hreq, - "TEARDOWN rtsp://%s/%s RTSP/1.0\r\n" - "CSeq: %d\r\n" - "Client-Instance: %s\r\n" - "User-Agent: %s\r\n" - "Session: %s\r\n" - "\r\n", - conn->host, - conn->url_abspath, ++conn->cseq, conn->cid, conn->ua, conn->session); - - gst_apexraop_send (conn->ctrl_sd, hreq, strlen (hreq)); - gst_apexraop_recv (conn->ctrl_sd, hreq, GST_APEX_RAOP_HDR_DEFAULT_LENGTH); - - if (conn->ctrl_sd != 0) - close (conn->ctrl_sd); - if (conn->data_sd != 0) - close (conn->data_sd); -} - -/* raop apex volume set */ -GstRTSPStatusCode -gst_apexraop_set_volume (GstApExRAOP * con, const guint volume) -{ - gint v; - gchar creq[GST_APEX_RAOP_SDP_DEFAULT_LENGTH], - hreq[GST_APEX_RAOP_HDR_DEFAULT_LENGTH], *req, vol[128]; - GstRTSPStatusCode res; - _GstApExRAOP *conn; - - conn = (_GstApExRAOP *) con; - - v = GST_APEX_RAOP_VOLUME_MIN + (GST_APEX_RAOP_VOLUME_MAX - - GST_APEX_RAOP_VOLUME_MIN) * volume / 100.; - sprintf (vol, "volume: %d.000000\r\n", v); - - sprintf (creq, "%s\r\n", vol); - - sprintf (hreq, - "SET_PARAMETER rtsp://%s/%s RTSP/1.0\r\n" - "CSeq: %d\r\n" - "Client-Instance: %s\r\n" - "User-Agent: %s\r\n" - "Session: %s\r\n" - "Content-Type: text/parameters\r\n" - "Content-Length: %u\r\n", - conn->host, - conn->url_abspath, - ++conn->cseq, conn->cid, conn->ua, conn->session, (guint) strlen (creq) - ); - - req = g_strconcat (hreq, "\r\n", creq, NULL); - - if (gst_apexraop_send (conn->ctrl_sd, req, strlen (req)) <= 0) { - g_free (req); - return GST_RTSP_STS_GONE; - } - - g_free (req); - - if (gst_apexraop_recv (conn->ctrl_sd, hreq, - GST_APEX_RAOP_HDR_DEFAULT_LENGTH) <= 0) - return GST_RTSP_STS_GONE; - - { - int tmp; - sscanf (hreq, "%*s %d", &tmp); - res = (GstRTSPStatusCode) tmp; - } - - return res; -} - -/* raop apex raw data alac encapsulation, encryption and emission, http://wiki.multimedia.cx/index.php?title=Apple_Lossless_Audio_Coding */ -static void inline -gst_apexraop_write_bits (guchar * buffer, int data, int numbits, - int *bit_offset, int *byte_offset) -{ - const static guchar masks[] = - { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; - - if (((*bit_offset) != 0) && (((*bit_offset) + numbits) > 8)) { - gint numwritebits; - guchar bitstowrite; - - numwritebits = 8 - (*bit_offset); - bitstowrite = - (guchar) ((data >> (numbits - numwritebits)) << (8 - (*bit_offset) - - numwritebits)); - buffer[(*byte_offset)] |= bitstowrite; - numbits -= numwritebits; - (*bit_offset) = 0; - (*byte_offset)++; - } - - while (numbits >= 8) { - guchar bitstowrite; - - bitstowrite = (guchar) ((data >> (numbits - 8)) & 0xFF); - buffer[(*byte_offset)] |= bitstowrite; - numbits -= 8; - (*bit_offset) = 0; - (*byte_offset)++; - } - - if (numbits > 0) { - guchar bitstowrite; - bitstowrite = - (guchar) ((data & masks[numbits]) << (8 - (*bit_offset) - numbits)); - buffer[(*byte_offset)] |= bitstowrite; - (*bit_offset) += numbits; - if ((*bit_offset) == 8) { - (*byte_offset)++; - (*bit_offset) = 0; - } - } -} - -guint -gst_apexraop_write (GstApExRAOP * con, gpointer rawdata, guint length) -{ - guchar *buffer, *frame_data; - gushort len; - gint bit_offset, byte_offset, i, out_len, res; - EVP_CIPHER_CTX aes_ctx; - _GstApExRAOP *conn = (_GstApExRAOP *) con; - const int frame_header_size = conn->generation == GST_APEX_GENERATION_ONE - ? GST_APEX_RAOP_FRAME_HEADER_SIZE : GST_APEX_RTP_FRAME_HEADER_SIZE; - - buffer = - (guchar *) g_malloc0 (frame_header_size + - GST_APEX_RAOP_ALAC_HEADER_SIZE + length); - - if (conn->generation == GST_APEX_GENERATION_ONE) { - g_assert (frame_header_size == GST_APEX_RAOP_FRAME_HEADER_SIZE); - memcpy (buffer, GST_APEX_RAOP_FRAME_HEADER, frame_header_size); - - len = length + frame_header_size + GST_APEX_RAOP_ALAC_HEADER_SIZE - 4; - - buffer[2] = len >> 8; - buffer[3] = len & 0xff; - } else { - /* Gen. 2 uses RTP-like header (RFC 3550). */ - short network_seq_num; - int network_timestamp, unknown_const; - static gboolean first = TRUE; - - buffer[0] = 0x80; - if (first) { - buffer[1] = 0xe0; - first = FALSE; - } else - buffer[1] = 0x60; - - network_seq_num = htons (conn->rtp_seq_num++); - memcpy (buffer + 2, &network_seq_num, 2); - - network_timestamp = htons (conn->rtp_timestamp); - memcpy (buffer + 4, &network_timestamp, 4); - conn->rtp_timestamp += GST_APEX_RAOP_V2_SAMPLES_PER_FRAME; - - unknown_const = 0xdeadbeef; - memcpy (buffer + 8, &unknown_const, 4); - } - - bit_offset = 0; - byte_offset = 0; - frame_data = buffer + frame_header_size; - - gst_apexraop_write_bits (frame_data, 1, 3, &bit_offset, &byte_offset); /* channels, 0 mono, 1 stereo */ - gst_apexraop_write_bits (frame_data, 0, 4, &bit_offset, &byte_offset); /* unknown */ - gst_apexraop_write_bits (frame_data, 0, 8, &bit_offset, &byte_offset); /* unknown (12 bits) */ - gst_apexraop_write_bits (frame_data, 0, 4, &bit_offset, &byte_offset); - gst_apexraop_write_bits (frame_data, 0, 1, &bit_offset, &byte_offset); /* has size flag */ - gst_apexraop_write_bits (frame_data, 0, 2, &bit_offset, &byte_offset); /* unknown */ - gst_apexraop_write_bits (frame_data, 1, 1, &bit_offset, &byte_offset); /* no compression flag */ - - for (i = 0; i < length; i += 2) { - gst_apexraop_write_bits (frame_data, ((guchar *) rawdata)[i + 1], 8, - &bit_offset, &byte_offset); - gst_apexraop_write_bits (frame_data, ((guchar *) rawdata)[i], 8, - &bit_offset, &byte_offset); - } - - EVP_CIPHER_CTX_init (&aes_ctx); - EVP_CipherInit_ex (&aes_ctx, EVP_aes_128_cbc (), NULL, conn->aes_ky, - conn->aes_iv, AES_ENCRYPT); - EVP_CipherUpdate (&aes_ctx, frame_data, &out_len, frame_data, /*( */ - GST_APEX_RAOP_ALAC_HEADER_SIZE + - length /*) / AES_BLOCK_SIZE * AES_BLOCK_SIZE */ ); - EVP_CIPHER_CTX_cleanup (&aes_ctx); - - res = - gst_apexraop_send (conn->data_sd, buffer, - frame_header_size + GST_APEX_RAOP_ALAC_HEADER_SIZE + length); - - g_free (buffer); - - return (guint) ((res >= - (frame_header_size + - GST_APEX_RAOP_ALAC_HEADER_SIZE)) ? (res - - frame_header_size - GST_APEX_RAOP_ALAC_HEADER_SIZE) : 0); -} - -/* raop apex buffer flush */ -GstRTSPStatusCode -gst_apexraop_flush (GstApExRAOP * con) -{ - gchar hreq[GST_APEX_RAOP_HDR_DEFAULT_LENGTH]; - GstRTSPStatusCode res; - _GstApExRAOP *conn; - - conn = (_GstApExRAOP *) con; - - sprintf (hreq, - "FLUSH rtsp://%s/%s RTSP/1.0\r\n" - "CSeq: %d\r\n" - "Client-Instance: %s\r\n" - "User-Agent: %s\r\n" - "Session: %s\r\n" - "RTP-Info: seq=%d;rtptime=%d\r\n" - "\r\n", - conn->host, - conn->url_abspath, - ++conn->cseq, - conn->cid, - conn->ua, conn->session, conn->rtp_seq_num, conn->rtp_timestamp); - - if (gst_apexraop_send (conn->ctrl_sd, hreq, strlen (hreq)) <= 0) - return GST_RTSP_STS_GONE; - - if (gst_apexraop_recv (conn->ctrl_sd, hreq, - GST_APEX_RAOP_HDR_DEFAULT_LENGTH) <= 0) - return GST_RTSP_STS_GONE; - - { - int tmp; - sscanf (hreq, "%*s %d", &tmp); - res = (GstRTSPStatusCode) tmp; - } - - return res; -} diff --git a/ext/apexsink/gstapexraop.h b/ext/apexsink/gstapexraop.h deleted file mode 100644 index a4f947e4f..000000000 --- a/ext/apexsink/gstapexraop.h +++ /dev/null @@ -1,148 +0,0 @@ -/* GStreamer - Remote Audio Access Protocol (RAOP) as used in Apple iTunes to stream music to the Airport Express (ApEx) - - * - * RAOP is based on the Real Time Streaming Protocol (RTSP) but with an extra challenge-response RSA based authentication step. - * This interface accepts RAW PCM data and set it as AES encrypted ALAC while performing emission. - * - * Copyright (C) 2008 Jérémie Bernard [GRemi] <gremimail@gmail.com> - * - * gstapexraop.h - * - * 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_APEXRAOP_H__ -#define __GST_APEXRAOP_H__ - -#include <gst/gst.h> -#include <gst/rtsp/gstrtspdefs.h> - -#include <openssl/rand.h> -#include <openssl/rsa.h> -#include <openssl/aes.h> -#include <openssl/evp.h> - -#include <string.h> -#include <stdlib.h> -#include <unistd.h> - -#include <netinet/in.h> -#include <netdb.h> - -#include <arpa/inet.h> - -G_BEGIN_DECLS - -/* raop fixed parameters */ -#define GST_APEX_RAOP_BITRATE 44100 -#define GST_APEX_RAOP_V1_SAMPLES_PER_FRAME 4096 -#define GST_APEX_RAOP_V2_SAMPLES_PER_FRAME 352 -#define GST_APEX_RAOP_BYTES_PER_CHANNEL 2 -#define GST_APEX_RAOP_CHANNELS 2 -#define GST_APEX_RAOP_BYTES_PER_SAMPLE (GST_APEX_RAOP_CHANNELS * GST_APEX_RAOP_BYTES_PER_CHANNEL) - -/* gst associated caps fields specification */ -#define GST_APEX_RAOP_INPUT_TYPE "audio/x-raw-int" -#define GST_APEX_RAOP_INPUT_WIDTH "16" -#define GST_APEX_RAOP_INPUT_DEPTH GST_APEX_RAOP_INPUT_WIDTH -#define GST_APEX_RAOP_INPUT_ENDIAN "LITTLE_ENDIAN" -#define GST_APEX_RAOP_INPUT_CHANNELS "2" -#define GST_APEX_RAOP_INPUT_BIT_RATE "44100" -#define GST_APEX_RAOP_INPUT_SIGNED "TRUE" - -typedef enum -{ - GST_APEX_JACK_TYPE_UNDEFINED = 0, - GST_APEX_JACK_TYPE_ANALOG, - GST_APEX_JACK_TYPE_DIGITAL, -} -GstApExJackType; - -typedef enum -{ - GST_APEX_JACK_STATUS_UNDEFINED = 0, - GST_APEX_JACK_STATUS_DISCONNECTED, - GST_APEX_JACK_STATUS_CONNECTED, -} -GstApExJackStatus; - -typedef enum -{ - GST_APEX_GENERATION_ONE = 1, - GST_APEX_GENERATION_TWO, -} -GstApExGeneration; - -typedef enum -{ - GST_APEX_TCP = 0, - GST_APEX_UDP, -} -GstApExTransportProtocol; - -/* raop context handle */ -typedef struct -{ -} GstApExRAOP; - -/* host might be null and port might be 0 while instanciating */ -GstApExRAOP *gst_apexraop_new (const gchar * host, - const guint16 port, - const GstApExGeneration generation, - const GstApExTransportProtocol transport_protocol); -void gst_apexraop_free (GstApExRAOP * conn); - -/* must not be connected yet while setting the host target */ -void gst_apexraop_set_host (GstApExRAOP * conn, const gchar * host); -gchar *gst_apexraop_get_host (GstApExRAOP * conn); - -/* must not be connected yet while setting the port target */ -void gst_apexraop_set_port (GstApExRAOP * conn, const guint16 port); -guint16 gst_apexraop_get_port (GstApExRAOP * conn); - -/* optional affectation, default iTunes user agent internaly used */ -void gst_apexraop_set_useragent (GstApExRAOP * conn, const gchar * useragent); -gchar *gst_apexraop_get_useragent (GstApExRAOP * conn); - -/* once allocation and configuration performed, manages the raop ANNOUNCE, SETUP and RECORD sequences, - * open both ctrl and data channels */ -GstRTSPStatusCode gst_apexraop_connect (GstApExRAOP * conn); - -/* close the currently used session, manages raop TEARDOWN sequence and closes the used sockets */ -void gst_apexraop_close (GstApExRAOP * conn); - -/* once connected, set the apex target volume, manages SET_PARAMETER sequence */ -GstRTSPStatusCode gst_apexraop_set_volume (GstApExRAOP * conn, - const guint volume); - -/* write raw samples typed as defined by the fixed raop parameters, flush the apex buffer */ -guint gst_apexraop_write (GstApExRAOP * conn, gpointer rawdata, guint length); -GstRTSPStatusCode gst_apexraop_flush (GstApExRAOP * conn); - -/* retrieve the connected apex jack type and status */ -GstApExJackType gst_apexraop_get_jacktype (GstApExRAOP * conn); -GstApExJackStatus gst_apexraop_get_jackstatus (GstApExRAOP * conn); - -/* retrieve the generation */ -GstApExGeneration gst_apexraop_get_generation (GstApExRAOP * conn); - -/* retrieve the transport protocol */ -GstApExTransportProtocol gst_apexraop_get_transport_protocol (GstApExRAOP * conn); - -G_END_DECLS - -#endif - diff --git a/ext/apexsink/gstapexsink.c b/ext/apexsink/gstapexsink.c deleted file mode 100644 index df5c5f256..000000000 --- a/ext/apexsink/gstapexsink.c +++ /dev/null @@ -1,665 +0,0 @@ -/* GStreamer - AirPort Express Audio Sink - - * - * Remote Audio Access Protocol (RAOP) as used in Apple iTunes to stream music to the Airport Express (ApEx) - - * RAOP is based on the Real Time Streaming Protocol (RTSP) but with an extra challenge-response RSA based authentication step. - * - * RAW PCM input only as defined by the following GST_STATIC_PAD_TEMPLATE - * - * Copyright (C) 2008 Jérémie Bernard [GRemi] <gremimail@gmail.com> - * - * gstapexsink.c - * - * 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 <string.h> - -#include "gstapexsink.h" - -GST_DEBUG_CATEGORY_STATIC (apexsink_debug); -#define GST_CAT_DEFAULT apexsink_debug - -static GstStaticPadTemplate gst_apexsink_sink_factory = GST_STATIC_PAD_TEMPLATE - ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS - (GST_APEX_RAOP_INPUT_TYPE "," - "width = (int) " GST_APEX_RAOP_INPUT_WIDTH "," - "depth = (int) " GST_APEX_RAOP_INPUT_DEPTH "," - "endianness = (int) " GST_APEX_RAOP_INPUT_ENDIAN "," - "channels = (int) " GST_APEX_RAOP_INPUT_CHANNELS "," - "rate = (int) " GST_APEX_RAOP_INPUT_BIT_RATE "," - "signed = (boolean) " GST_APEX_RAOP_INPUT_SIGNED) - ); - - -enum -{ - APEX_PROP_HOST = 1, - APEX_PROP_PORT, - APEX_PROP_VOLUME, - APEX_PROP_JACK_TYPE, - APEX_PROP_JACK_STATUS, - APEX_PROP_GENERATION, - APEX_PROP_TRANSPORT_PROTOCOL, -}; - -#define DEFAULT_APEX_HOST "" -#define DEFAULT_APEX_PORT 5000 -#define DEFAULT_APEX_VOLUME 1.0 -#define DEFAULT_APEX_JACK_TYPE GST_APEX_JACK_TYPE_UNDEFINED -#define DEFAULT_APEX_JACK_STATUS GST_APEX_JACK_STATUS_UNDEFINED -#define DEFAULT_APEX_GENERATION GST_APEX_GENERATION_ONE -#define DEFAULT_APEX_TRANSPORT_PROTOCOL GST_APEX_TCP - -/* genum apex jack resolution */ -GType -gst_apexsink_jackstatus_get_type (void) -{ - static GType jackstatus_type = 0; - static const GEnumValue jackstatus[] = { - {GST_APEX_JACK_STATUS_UNDEFINED, "GST_APEX_JACK_STATUS_UNDEFINED", - "Jack status undefined"}, - {GST_APEX_JACK_STATUS_DISCONNECTED, "GST_APEX_JACK_STATUS_DISCONNECTED", - "Jack disconnected"}, - {GST_APEX_JACK_STATUS_CONNECTED, "GST_APEX_JACK_STATUS_CONNECTED", - "Jack connected"}, - {0, NULL, NULL}, - }; - - if (!jackstatus_type) { - jackstatus_type = g_enum_register_static ("GstApExJackStatus", jackstatus); - } - - return jackstatus_type; -} - -GType -gst_apexsink_jacktype_get_type (void) -{ - static GType jacktype_type = 0; - static const GEnumValue jacktype[] = { - {GST_APEX_JACK_TYPE_UNDEFINED, "GST_APEX_JACK_TYPE_UNDEFINED", - "Undefined jack type"}, - {GST_APEX_JACK_TYPE_ANALOG, "GST_APEX_JACK_TYPE_ANALOG", "Analog jack"}, - {GST_APEX_JACK_TYPE_DIGITAL, "GST_APEX_JACK_TYPE_DIGITAL", "Digital jack"}, - {0, NULL, NULL}, - }; - - if (!jacktype_type) { - jacktype_type = g_enum_register_static ("GstApExJackType", jacktype); - } - - return jacktype_type; -} - -GType -gst_apexsink_generation_get_type (void) -{ - static GType generation_type = 0; - static const GEnumValue generation[] = { - {GST_APEX_GENERATION_ONE, "generation-one", - "First generation (e.g., original AirPort Express)"}, - {GST_APEX_GENERATION_TWO, "generation-two", - "Second generation (e.g., Apple TV v2)"}, - {0, NULL, NULL}, - }; - - if (!generation_type) { - generation_type = g_enum_register_static ("GstApExGeneration", generation); - } - - return generation_type; -} - -GType -gst_apexsink_transport_protocol_get_type (void) -{ - static GType transport_protocol_type = 0; - static const GEnumValue transport_protocol[] = { - {GST_APEX_TCP, "tcp", "TCP"}, - {GST_APEX_UDP, "udp", "UDP"}, - {0, NULL, NULL}, - }; - - if (!transport_protocol_type) { - transport_protocol_type = - g_enum_register_static ("GstApExTransportProtocol", transport_protocol); - } - - return transport_protocol_type; -} - - -static void gst_apexsink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_apexsink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_apexsink_finalise (GObject * object); - -static gboolean gst_apexsink_open (GstAudioSink * asink); -static gboolean gst_apexsink_prepare (GstAudioSink * asink, - GstRingBufferSpec * spec); -static guint gst_apexsink_write (GstAudioSink * asink, gpointer data, - guint length); -static gboolean gst_apexsink_unprepare (GstAudioSink * asink); -static guint gst_apexsink_delay (GstAudioSink * asink); -static void gst_apexsink_reset (GstAudioSink * asink); -static gboolean gst_apexsink_close (GstAudioSink * asink); -static GstStateChangeReturn gst_apexsink_change_state (GstElement * element, - GstStateChange transition); - -/* mixer interface standard api */ -static void gst_apexsink_interfaces_init (GType type); -static void gst_apexsink_implements_interface_init (GstImplementsInterfaceClass - * iface); -static void gst_apexsink_mixer_interface_init (GstMixerInterface * iface); - -static gboolean gst_apexsink_interface_supported (GstImplementsInterface * - iface, GType iface_type); -static const GList *gst_apexsink_mixer_list_tracks (GstMixer * mixer); -static void gst_apexsink_mixer_set_volume (GstMixer * mixer, - GstMixerTrack * track, gint * volumes); -static void gst_apexsink_mixer_get_volume (GstMixer * mixer, - GstMixerTrack * track, gint * volumes); - -GST_BOILERPLATE_FULL (GstApExSink, gst_apexsink, GstAudioSink, - GST_TYPE_AUDIO_SINK, gst_apexsink_interfaces_init); - -/* apex sink interface(s) stuff */ -static void -gst_apexsink_interfaces_init (GType type) -{ - static const GInterfaceInfo implements_interface_info = - { (GInterfaceInitFunc) gst_apexsink_implements_interface_init, NULL, - NULL - }; - static const GInterfaceInfo mixer_interface_info = - { (GInterfaceInitFunc) gst_apexsink_mixer_interface_init, NULL, NULL }; - - g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, - &implements_interface_info); - g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_interface_info); -} - -static void -gst_apexsink_implements_interface_init (GstImplementsInterfaceClass * iface) -{ - iface->supported = gst_apexsink_interface_supported; -} - -static void -gst_apexsink_mixer_interface_init (GstMixerInterface * iface) -{ - GST_MIXER_TYPE (iface) = GST_MIXER_SOFTWARE; - - iface->list_tracks = gst_apexsink_mixer_list_tracks; - iface->set_volume = gst_apexsink_mixer_set_volume; - iface->get_volume = gst_apexsink_mixer_get_volume; -} - -static gboolean -gst_apexsink_interface_supported (GstImplementsInterface * iface, - GType iface_type) -{ - g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE); - - return TRUE; -} - -static const GList * -gst_apexsink_mixer_list_tracks (GstMixer * mixer) -{ - GstApExSink *apexsink = GST_APEX_SINK (mixer); - - return apexsink->tracks; -} - -static void -gst_apexsink_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track, - gint * volumes) -{ - GstApExSink *apexsink = GST_APEX_SINK (mixer); - - apexsink->volume = volumes[0]; - - if (apexsink->gst_apexraop != NULL) - gst_apexraop_set_volume (apexsink->gst_apexraop, apexsink->volume); -} - -static void -gst_apexsink_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track, - gint * volumes) -{ - GstApExSink *apexsink = GST_APEX_SINK (mixer); - - volumes[0] = apexsink->volume; -} - -/* sink base init */ -static void -gst_apexsink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_static_metadata (element_class, - "Apple AirPort Express Audio Sink", "Sink/Audio/Wireless", - "Output stream to an AirPort Express", - "Jérémie Bernard [GRemi] <gremimail@gmail.com>"); - gst_element_class_add_static_pad_template (element_class, - &gst_apexsink_sink_factory); -} - -/* sink class init */ -static void -gst_apexsink_class_init (GstApExSinkClass * klass) -{ - GST_DEBUG_CATEGORY_INIT (apexsink_debug, GST_APEX_SINK_NAME, 0, - "AirPort Express sink"); - - parent_class = g_type_class_peek_parent (klass); - - ((GObjectClass *) klass)->get_property = - GST_DEBUG_FUNCPTR (gst_apexsink_get_property); - ((GObjectClass *) klass)->set_property = - GST_DEBUG_FUNCPTR (gst_apexsink_set_property); - ((GObjectClass *) klass)->finalize = - GST_DEBUG_FUNCPTR (gst_apexsink_finalise); - - ((GstAudioSinkClass *) klass)->open = GST_DEBUG_FUNCPTR (gst_apexsink_open); - ((GstAudioSinkClass *) klass)->prepare = - GST_DEBUG_FUNCPTR (gst_apexsink_prepare); - ((GstAudioSinkClass *) klass)->write = GST_DEBUG_FUNCPTR (gst_apexsink_write); - ((GstAudioSinkClass *) klass)->unprepare = - GST_DEBUG_FUNCPTR (gst_apexsink_unprepare); - ((GstAudioSinkClass *) klass)->delay = GST_DEBUG_FUNCPTR (gst_apexsink_delay); - ((GstAudioSinkClass *) klass)->reset = GST_DEBUG_FUNCPTR (gst_apexsink_reset); - ((GstAudioSinkClass *) klass)->close = GST_DEBUG_FUNCPTR (gst_apexsink_close); - - ((GstElementClass *) klass)->change_state = - GST_DEBUG_FUNCPTR (gst_apexsink_change_state); - - g_object_class_install_property ((GObjectClass *) klass, APEX_PROP_HOST, - g_param_spec_string ("host", "Host", "AirPort Express target host", - DEFAULT_APEX_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property ((GObjectClass *) klass, APEX_PROP_PORT, - g_param_spec_uint ("port", "Port", "AirPort Express target port", 0, - 32000, DEFAULT_APEX_PORT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /* we need to expose the volume as a double for playbin. Internally we keep - * it as an int between 0 and 100, where 75 corresponds to 1.0. - * FIXME we should store the volume as a double. */ - g_object_class_install_property ((GObjectClass *) klass, APEX_PROP_VOLUME, - g_param_spec_double ("volume", "Volume", "AirPort Express target volume", - 0.0, 10.0, DEFAULT_APEX_VOLUME, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property ((GObjectClass *) klass, APEX_PROP_JACK_TYPE, - g_param_spec_enum ("jack-type", "Jack Type", - "AirPort Express connected jack type", GST_APEX_SINK_JACKTYPE_TYPE, - DEFAULT_APEX_JACK_TYPE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property ((GObjectClass *) klass, - APEX_PROP_JACK_STATUS, g_param_spec_enum ("jack-status", "Jack Status", - "AirPort Express jack connection status", - GST_APEX_SINK_JACKSTATUS_TYPE, DEFAULT_APEX_JACK_STATUS, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property ((GObjectClass *) klass, - APEX_PROP_GENERATION, g_param_spec_enum ("generation", "Generation", - "AirPort device generation", - GST_APEX_SINK_GENERATION_TYPE, DEFAULT_APEX_GENERATION, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property ((GObjectClass *) klass, - APEX_PROP_TRANSPORT_PROTOCOL, g_param_spec_enum ("transport-protocol", - "Transport Protocol", "AirPort transport protocol", - GST_APEX_SINK_TRANSPORT_PROTOCOL_TYPE, - DEFAULT_APEX_TRANSPORT_PROTOCOL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -/* sink plugin instance init */ -static void -gst_apexsink_init (GstApExSink * apexsink, GstApExSinkClass * g_class) -{ - GstMixerTrack *track = NULL; - - track = g_object_new (GST_TYPE_MIXER_TRACK, NULL); - track->label = g_strdup ("Airport Express"); - track->num_channels = GST_APEX_RAOP_CHANNELS; - track->min_volume = 0; - track->max_volume = 100; - track->flags = GST_MIXER_TRACK_OUTPUT; - - apexsink->host = g_strdup (DEFAULT_APEX_HOST); - apexsink->port = DEFAULT_APEX_PORT; - apexsink->volume = CLAMP (DEFAULT_APEX_VOLUME * 75, 0, 100); - apexsink->gst_apexraop = NULL; - apexsink->tracks = g_list_append (apexsink->tracks, track); - apexsink->clock = gst_system_clock_obtain (); - apexsink->clock_id = NULL; - - GST_INFO_OBJECT (apexsink, - "ApEx sink default initialization, target=\"%s\", port=\"%d\", volume=\"%d%%\"", - apexsink->host, apexsink->port, apexsink->volume); -} - -/* apex sink set property */ -static void -gst_apexsink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstApExSink *sink = GST_APEX_SINK (object); - - switch (prop_id) { - case APEX_PROP_HOST: - if (sink->gst_apexraop == NULL) { - g_free (sink->host); - sink->host = g_value_dup_string (value); - - GST_INFO_OBJECT (sink, "ApEx sink target set to \"%s\"", sink->host); - } else { - G_OBJECT_WARN_INVALID_PSPEC (object, "host", prop_id, pspec); - } - break; - case APEX_PROP_PORT: - if (sink->gst_apexraop == NULL) { - sink->port = g_value_get_uint (value); - - GST_INFO_OBJECT (sink, "ApEx port set to \"%d\"", sink->port); - } else { - G_OBJECT_WARN_INVALID_PSPEC (object, "port", prop_id, pspec); - } - break; - case APEX_PROP_VOLUME: - { - gdouble volume; - - volume = g_value_get_double (value); - volume *= 75.0; - - sink->volume = CLAMP (volume, 0, 100); - - if (sink->gst_apexraop != NULL) - gst_apexraop_set_volume (sink->gst_apexraop, sink->volume); - - GST_INFO_OBJECT (sink, "ApEx volume set to \"%d%%\"", sink->volume); - break; - } - case APEX_PROP_GENERATION: - if (sink->gst_apexraop == NULL) { - sink->generation = g_value_get_enum (value); - - GST_INFO_OBJECT (sink, "ApEx generation set to \"%d\"", - sink->generation); - } else { - GST_WARNING_OBJECT (sink, - "SET-PROPERTY : generation property may not be set when apexsink opened !"); - } - break; - case APEX_PROP_TRANSPORT_PROTOCOL: - if (sink->gst_apexraop == NULL) { - sink->transport_protocol = g_value_get_enum (value); - - GST_INFO_OBJECT (sink, "ApEx transport protocol set to \"%d\"", - sink->transport_protocol); - } else { - GST_WARNING_OBJECT (sink, - "SET-PROPERTY : transport protocol property may not be set when apexsink opened !"); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* apex sink get property */ -static void -gst_apexsink_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstApExSink *sink = GST_APEX_SINK (object); - - switch (prop_id) { - case APEX_PROP_HOST: - g_value_set_string (value, sink->host); - break; - case APEX_PROP_PORT: - g_value_set_uint (value, sink->port); - break; - case APEX_PROP_VOLUME: - g_value_set_double (value, ((gdouble) sink->volume) / 75.0); - break; - case APEX_PROP_JACK_TYPE: - g_value_set_enum (value, gst_apexraop_get_jacktype (sink->gst_apexraop)); - break; - case APEX_PROP_JACK_STATUS: - g_value_set_enum (value, - gst_apexraop_get_jackstatus (sink->gst_apexraop)); - break; - case APEX_PROP_GENERATION: - g_value_set_enum (value, - gst_apexraop_get_generation (sink->gst_apexraop)); - break; - case APEX_PROP_TRANSPORT_PROTOCOL: - g_value_set_enum (value, - gst_apexraop_get_transport_protocol (sink->gst_apexraop)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* apex sink finalize */ -static void -gst_apexsink_finalise (GObject * object) -{ - GstApExSink *sink = GST_APEX_SINK (object); - - if (sink->tracks) { - g_list_foreach (sink->tracks, (GFunc) g_object_unref, NULL); - g_list_free (sink->tracks); - sink->tracks = NULL; - } - - gst_object_unref (sink->clock); - - g_free (sink->host); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -/* sink open : open the device */ -static gboolean -gst_apexsink_open (GstAudioSink * asink) -{ - int res; - GstApExSink *apexsink = (GstApExSink *) asink; - - apexsink->gst_apexraop = gst_apexraop_new (apexsink->host, - apexsink->port, apexsink->generation, apexsink->transport_protocol); - - if ((res = gst_apexraop_connect (apexsink->gst_apexraop)) != GST_RTSP_STS_OK) { - GST_ERROR_OBJECT (apexsink, - "%s : network or RAOP failure, connection refused or timeout, RTSP code=%d", - apexsink->host, res); - return FALSE; - } - - GST_INFO_OBJECT (apexsink, - "OPEN : ApEx sink successfully connected to \"%s:%d\", ANNOUNCE, SETUP and RECORD requests performed", - apexsink->host, apexsink->port); - - switch (gst_apexraop_get_jackstatus (apexsink->gst_apexraop)) { - case GST_APEX_JACK_STATUS_CONNECTED: - GST_INFO_OBJECT (apexsink, "OPEN : ApEx jack is connected"); - break; - case GST_APEX_JACK_STATUS_DISCONNECTED: - GST_WARNING_OBJECT (apexsink, "OPEN : ApEx jack is disconnected !"); - break; - default: - GST_WARNING_OBJECT (apexsink, "OPEN : ApEx jack status is undefined !"); - break; - } - - switch (gst_apexraop_get_jacktype (apexsink->gst_apexraop)) { - case GST_APEX_JACK_TYPE_ANALOG: - GST_INFO_OBJECT (apexsink, "OPEN : ApEx jack type is analog"); - break; - case GST_APEX_JACK_TYPE_DIGITAL: - GST_INFO_OBJECT (apexsink, "OPEN : ApEx jack type is digital"); - break; - default: - GST_WARNING_OBJECT (apexsink, "OPEN : ApEx jack type is undefined !"); - break; - } - - if ((res = - gst_apexraop_set_volume (apexsink->gst_apexraop, - apexsink->volume)) != GST_RTSP_STS_OK) { - GST_WARNING_OBJECT (apexsink, - "%s : could not set initial volume to \"%d%%\", RTSP code=%d", - apexsink->host, apexsink->volume, res); - } else { - GST_INFO_OBJECT (apexsink, - "OPEN : ApEx sink successfully set volume to \"%d%%\"", - apexsink->volume); - } - - return TRUE; -} - -/* prepare sink : configure the device with the specified format */ -static gboolean -gst_apexsink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) -{ - GstApExSink *apexsink = (GstApExSink *) asink; - GstApExGeneration gen = gst_apexraop_get_generation (apexsink->gst_apexraop); - - apexsink->latency_time = spec->latency_time; - - spec->segsize = gen == GST_APEX_GENERATION_ONE - ? GST_APEX_RAOP_V1_SAMPLES_PER_FRAME * GST_APEX_RAOP_BYTES_PER_SAMPLE - : GST_APEX_RAOP_V2_SAMPLES_PER_FRAME * GST_APEX_RAOP_BYTES_PER_SAMPLE; - spec->segtotal = 2; - - memset (spec->silence_sample, 0, sizeof (spec->silence_sample)); - - GST_INFO_OBJECT (apexsink, - "PREPARE : ApEx sink ready to stream at %dHz, %d bytes per sample, %d channels, %d bytes segments (%dkB/s)", - spec->rate, spec->bytes_per_sample, spec->channels, spec->segsize, - spec->rate * spec->bytes_per_sample / 1000); - - return TRUE; -} - -/* sink write : write samples to the device */ -static guint -gst_apexsink_write (GstAudioSink * asink, gpointer data, guint length) -{ - guint written; - GstApExSink *apexsink = (GstApExSink *) asink; - - if ((written = - gst_apexraop_write (apexsink->gst_apexraop, data, - length)) != length) { - GST_INFO_OBJECT (apexsink, - "WRITE : %d of %d bytes sent, skipping frame samples...", written, - length); - } else { - GST_INFO_OBJECT (apexsink, "WRITE : %d bytes sent", length); - /* NOTE, previous calculation subtracted apexsink->latency_time from this; - * however, the value below is less than apexsink->latency_time for generation 2. - * In this case, the number went negative (actualy wrapped around into a big number). - */ - apexsink->clock_id = gst_clock_new_single_shot_id (apexsink->clock, - (GstClockTime) (gst_clock_get_time (apexsink->clock) + - ((length * 1000000000.) - / (GST_APEX_RAOP_BITRATE * GST_APEX_RAOP_BYTES_PER_SAMPLE)))); - gst_clock_id_wait (apexsink->clock_id, NULL); - gst_clock_id_unref (apexsink->clock_id); - apexsink->clock_id = NULL; - } - - return length; -} - -/* unprepare sink : undo operations done by prepare */ -static gboolean -gst_apexsink_unprepare (GstAudioSink * asink) -{ - GST_INFO_OBJECT (asink, "UNPREPARE"); - - return TRUE; -} - -/* delay sink : get the estimated number of samples written but not played yet by the device */ -static guint -gst_apexsink_delay (GstAudioSink * asink) -{ - GST_LOG_OBJECT (asink, "DELAY"); - - return 0; -} - -/* reset sink : unblock writes and flush the device */ -static void -gst_apexsink_reset (GstAudioSink * asink) -{ - int res; - GstApExSink *apexsink = (GstApExSink *) asink; - - GST_INFO_OBJECT (apexsink, "RESET : flushing buffer..."); - - if ((res = gst_apexraop_flush (apexsink->gst_apexraop)) == GST_RTSP_STS_OK) { - GST_INFO_OBJECT (apexsink, "RESET : ApEx buffer flush success"); - } else { - GST_WARNING_OBJECT (apexsink, - "RESET : could not flush ApEx buffer, RTSP code=%d", res); - } -} - -/* sink close : close the device */ -static gboolean -gst_apexsink_close (GstAudioSink * asink) -{ - GstApExSink *apexsink = (GstApExSink *) asink; - - gst_apexraop_close (apexsink->gst_apexraop); - gst_apexraop_free (apexsink->gst_apexraop); - - GST_INFO_OBJECT (apexsink, "CLOSE : ApEx sink closed connection"); - - return TRUE; -} - -static GstStateChangeReturn -gst_apexsink_change_state (GstElement * element, GstStateChange transition) -{ - GstApExSink *apexsink = (GstApExSink *) element; - - if (apexsink->clock_id && transition == GST_STATE_CHANGE_PAUSED_TO_READY) { - gst_clock_id_unschedule (apexsink->clock_id); - gst_clock_id_unref (apexsink->clock_id); - apexsink->clock_id = NULL; - } - return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); -} diff --git a/ext/apexsink/gstapexsink.h b/ext/apexsink/gstapexsink.h deleted file mode 100644 index 711cd3725..000000000 --- a/ext/apexsink/gstapexsink.h +++ /dev/null @@ -1,98 +0,0 @@ -/* GStreamer - AirPort Express (ApEx) Audio Sink - - * - * Remote Audio Access Protocol (RAOP) as used in Apple iTunes to stream music to the Airport Express (ApEx) - - * RAOP is based on the Real Time Streaming Protocol (RTSP) but with an extra challenge-response RSA based authentication step. - * - * RAW PCM input only as defined by the following GST_STATIC_PAD_TEMPLATE regarding the expected gstapexraop input format. - * - * Copyright (C) 2008 Jérémie Bernard [GRemi] <gremimail@gmail.com> - * - * gstapexsink.h - * - * 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_APEXSINK_H__ -#define __GST_APEXSINK_H__ - -#include "gstapexraop.h" - -#include <gst/audio/gstaudiosink.h> -#include <gst/interfaces/mixer.h> - -G_BEGIN_DECLS - -/* standard gstreamer macros */ -#define GST_TYPE_APEX_SINK (gst_apexsink_get_type()) -#define GST_APEX_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_APEX_SINK,GstApExSink)) -#define GST_APEX_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_APEX_SINK,GstApExSinkClass)) -#define GST_IS_APEX_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_APEX_SINK)) -#define GST_IS_APEX_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_APEX_SINK)) -#define GST_APEX_SINK_CAST(obj) ((GstApExSink*)(obj)) -#define GST_APEX_SINK_NAME "apexsink" -#define GST_APEX_SINK_JACKTYPE_TYPE (gst_apexsink_jacktype_get_type()) -#define GST_APEX_SINK_JACKSTATUS_TYPE (gst_apexsink_jackstatus_get_type()) -#define GST_APEX_SINK_GENERATION_TYPE (gst_apexsink_generation_get_type()) -#define GST_APEX_SINK_TRANSPORT_PROTOCOL_TYPE (gst_apexsink_transport_protocol_get_type()) -/* ApEx classes declaration */ -typedef struct _GstApExSink GstApExSink; -typedef struct _GstApExSinkClass GstApExSinkClass; - -struct _GstApExSink -{ - /* base definition */ - GstAudioSink sink; - - /* public read/write sink properties */ - gchar *host; - guint port; - guint volume; - GstApExGeneration generation; - GstApExTransportProtocol transport_protocol; - - /* private attributes : - * latency time local copy - * tracks list of the mixer interface - * clock for sleeping - * clock ID for sleeping / canceling sleep - */ - guint64 latency_time; - GList *tracks; - GstClock *clock; - GstClockID clock_id; - - /* private apex client */ - GstApExRAOP *gst_apexraop; -}; - -struct _GstApExSinkClass -{ - GstAudioSinkClass parent_class; -}; - -/* genums */ -GType gst_apexsink_jackstatus_get_type (void); -GType gst_apexsink_jacktype_get_type (void); -GType gst_apexsink_generation_get_type (void); -GType gst_apexsink_transport_protocol_get_type (void); - -/* audio sink standard api */ -GType gst_apexsink_get_type (void); - -G_END_DECLS - -#endif diff --git a/ext/libvisual/Makefile.am b/ext/libvisual/Makefile.am deleted file mode 100644 index 1eba9af2f..000000000 --- a/ext/libvisual/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -plugin_LTLIBRARIES = libgstlibvisualgl.la - -libgstlibvisualgl_la_SOURCES = visual-gl.c - -libgstlibvisualgl_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(LIBVISUAL_CFLAGS) \ - -I$(top_srcdir)/gst-libs \ - -I$(top_srcdir)/gst-libs/gst/gl - -libgstlibvisualgl_la_LIBADD = \ - $(top_builddir)/gst-libs/gst/gl/libgstgl-$(GST_API_VERSION).la \ - $(GST_PLUGINS_BASE_LIBS) $(GST_LIBS) $(LIBVISUAL_LIBS) - -libgstlibvisualgl_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstlibvisualgl_la_LIBTOOLFLAGS = --tag=disable-static - diff --git a/ext/libvisual/visual-gl.c b/ext/libvisual/visual-gl.c deleted file mode 100644 index c796d4b47..000000000 --- a/ext/libvisual/visual-gl.c +++ /dev/null @@ -1,1248 +0,0 @@ -/* GStreamer - * Copyright (C) 2004 Benjamin Otte <otte@gnome.org> - * Copyright (C) 2009 Jonathan Matthew <notverysmart@gmail.com> - * Copyright (C) 2011 Julien Isorce <julien.isorce@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-libvisualgl - * - * Wrapper for libvisual plugins that use OpenGL - * - * <refsect2> - * <title>Examples</title> - * |[ - * gst-launch-1.0 -v audiotestsrc ! libvisual_gl_lv_flower ! glimagesink - * ]| - * </refsect2> - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gst/gst.h> -#include <gst/base/gstadapter.h> -#include <gst/video/video.h> -#include <gst/audio/audio.h> -#include <gst/gl/gstglbuffer.h> -#include <gst/gl/gstgldisplay.h> - -#include <libvisual/libvisual.h> - -#define GST_TYPE_VISUAL_GL (gst_visual_gl_get_type()) -#define GST_IS_VISUAL_GL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VISUAL_GL)) -#define GST_VISUAL_GL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VISUAL_GL,GstVisualGL)) -#define GST_IS_VISUAL_GL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VISUAL_GL)) -#define GST_VISUAL_GL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VISUAL_GL,GstVisualGLClass)) -#define GST_VISUAL_GL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VISUAL_GL, GstVisualGLClass)) - -typedef struct _GstVisualGL GstVisualGL; -typedef struct _GstVisualGLClass GstVisualGLClass; - -/* XXX use same category as libvisual plugin in -base? */ -GST_DEBUG_CATEGORY_STATIC (libvisual_debug); -#define GST_CAT_DEFAULT (libvisual_debug) - -/* amounf of samples before we can feed libvisual */ -#define VISUAL_SAMPLES 512 - -#define DEFAULT_WIDTH 320 -#define DEFAULT_HEIGHT 240 -#define DEFAULT_FPS_N 25 -#define DEFAULT_FPS_D 1 - -struct _GstVisualGL -{ - GstElement element; - - /* pads */ - GstPad *sinkpad; - GstPad *srcpad; - GstSegment segment; - - /* GL stuff */ - GstGLDisplay *display; - GLuint fbo; - GLuint depthbuffer; - GLuint midtexture; - GLdouble actor_projection_matrix[16]; - GLdouble actor_modelview_matrix[16]; - GLboolean is_enabled_gl_depth_test; - GLint gl_depth_func; - GLboolean is_enabled_gl_blend; - GLint gl_blend_src_alpha; - - /* libvisual stuff */ - VisAudio *audio; - VisVideo *video; - VisActor *actor; - int actor_setup_result; - - /* audio/video state */ - gint channels; - gint rate; /* Input samplerate */ - gint bps; - VisAudioSampleRateType libvisual_rate; - - /* framerate numerator & denominator */ - gint fps_n; - gint fps_d; - gint width; - gint height; - GstClockTime duration; - guint outsize; - - /* samples per frame based on caps */ - guint spf; - - /* state stuff */ - GstAdapter *adapter; - guint count; - - /* QoS stuff *//* with LOCK */ - gdouble proportion; - GstClockTime earliest_time; -}; - -struct _GstVisualGLClass -{ - GstElementClass parent_class; - - VisPluginRef *plugin; -}; - -GType gst_visual_gl_get_type (void); - - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_GL_VIDEO_CAPS) - ); - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "width = (int) 16, " - "depth = (int) 16, " - "endianness = (int) BYTE_ORDER, " - "signed = (boolean) TRUE, " "channels = (int) { 1, 2 }, " - "rate = (int) { 8000, 11250, 22500, 32000, 44100, 48000, 96000 }") - ); - - -static void gst_visual_gl_class_init (gpointer g_class, gpointer class_data); -static void gst_visual_gl_init (GstVisualGL * visual); -static void gst_visual_gl_dispose (GObject * object); - -static GstStateChangeReturn gst_visual_gl_change_state (GstElement * element, - GstStateChange transition); -static GstFlowReturn gst_visual_gl_chain (GstPad * pad, GstBuffer * buffer); -static gboolean gst_visual_gl_sink_event (GstPad * pad, GstEvent * event); -static gboolean gst_visual_gl_src_event (GstPad * pad, GstEvent * event); - -static gboolean gst_visual_gl_src_query (GstPad * pad, GstQuery * query); - -static gboolean gst_visual_gl_sink_setcaps (GstPad * pad, GstCaps * caps); -static gboolean gst_visual_gl_src_setcaps (GstPad * pad, GstCaps * caps); -static GstCaps *gst_visual_gl_getcaps (GstPad * pad); -static void libvisual_log_handler (const char *message, const char *funcname, - void *priv); - -static GstElementClass *parent_class = NULL; - -GType -gst_visual_gl_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo info = { - sizeof (GstVisualGLClass), - NULL, - NULL, - gst_visual_gl_class_init, - NULL, - NULL, - sizeof (GstVisualGL), - 0, - (GInstanceInitFunc) gst_visual_gl_init, - }; - - type = g_type_register_static (GST_TYPE_ELEMENT, "GstVisualGL", &info, 0); - } - return type; -} - -static void -libvisual_log_handler (const char *message, const char *funcname, void *priv) -{ - GST_CAT_LEVEL_LOG (libvisual_debug, (GstDebugLevel) (priv), NULL, "%s - %s", - funcname, message); -} - -static void -gst_visual_gl_class_init (gpointer g_class, gpointer class_data) -{ - GstVisualGLClass *klass = GST_VISUAL_GL_CLASS (g_class); - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GObjectClass *object = G_OBJECT_CLASS (g_class); - - klass->plugin = class_data; - - element_class->change_state = gst_visual_gl_change_state; - - if (class_data == NULL) { - parent_class = g_type_class_peek_parent (g_class); - } else { - char *longname = g_strdup_printf ("libvisual %s plugin v.%s", - klass->plugin->info->name, klass->plugin->info->version); - - /* FIXME: improve to only register what plugin supports? */ - gst_element_class_add_static_pad_template (element_class, &src_template); - gst_element_class_add_static_pad_template (element_class, &sink_template); - - gst_element_class_set_metadata (element_class, - longname, "Visualization", klass->plugin->info->about, - "Benjamin Otte <otte@gnome.org>"); - - g_free (longname); - } - - object->dispose = gst_visual_gl_dispose; -} - -static void -gst_visual_gl_init (GstVisualGL * visual) -{ - /* create the sink and src pads */ - visual->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_pad_set_setcaps_function (visual->sinkpad, gst_visual_gl_sink_setcaps); - gst_pad_set_chain_function (visual->sinkpad, gst_visual_gl_chain); - gst_pad_set_event_function (visual->sinkpad, gst_visual_gl_sink_event); - gst_element_add_pad (GST_ELEMENT (visual), visual->sinkpad); - - visual->srcpad = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_set_setcaps_function (visual->srcpad, gst_visual_gl_src_setcaps); - gst_pad_set_getcaps_function (visual->srcpad, gst_visual_gl_getcaps); - gst_pad_set_event_function (visual->srcpad, gst_visual_gl_src_event); - gst_pad_set_query_function (visual->srcpad, gst_visual_gl_src_query); - gst_element_add_pad (GST_ELEMENT (visual), visual->srcpad); - - visual->adapter = gst_adapter_new (); - - visual->actor = NULL; - - visual->display = NULL; - visual->fbo = 0; - visual->depthbuffer = 0; - visual->midtexture = 0; - - visual->is_enabled_gl_depth_test = GL_FALSE; - visual->gl_depth_func = GL_LESS; - visual->is_enabled_gl_blend = GL_FALSE; - visual->gl_blend_src_alpha = GL_ONE; -} - -static void -gst_visual_gl_clear_actors (GstVisualGL * visual) -{ - if (visual->actor) { - visual_object_unref (VISUAL_OBJECT (visual->actor)); - visual->actor = NULL; - } - if (visual->video) { - visual_object_unref (VISUAL_OBJECT (visual->video)); - visual->video = NULL; - } - if (visual->audio) { - visual_object_unref (VISUAL_OBJECT (visual->audio)); - visual->audio = NULL; - } -} - -static void -gst_visual_gl_dispose (GObject * object) -{ - GstVisualGL *visual = GST_VISUAL_GL (object); - - if (visual->adapter) { - gst_object_unref (visual->adapter); - visual->adapter = NULL; - } - - GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); -} - -static void -gst_visual_gl_reset (GstVisualGL * visual) -{ - gst_adapter_clear (visual->adapter); - gst_segment_init (&visual->segment, GST_FORMAT_UNDEFINED); - - GST_OBJECT_LOCK (visual); - visual->proportion = 1.0; - visual->earliest_time = -1; - GST_OBJECT_UNLOCK (visual); -} - -static GstCaps * -gst_visual_gl_getcaps (GstPad * pad) -{ - GstCaps *ret; - GstVisualGL *visual = GST_VISUAL_GL (gst_pad_get_parent (pad)); - int depths; - - if (!visual->actor) { - ret = gst_caps_copy (gst_pad_get_pad_template_caps (visual->srcpad)); - goto beach; - } - - ret = gst_caps_new_empty (); - depths = visual_actor_get_supported_depth (visual->actor); - if (depths < 0) { - /* FIXME: set an error */ - goto beach; - } - if ((depths & VISUAL_VIDEO_DEPTH_GL) == 0) { - /* We don't handle non-GL plugins */ - goto beach; - } - - GST_DEBUG_OBJECT (visual, "libvisual-gl plugin supports depths %u (0x%04x)", - depths, depths); - /* only do GL output */ - gst_caps_append (ret, gst_caps_from_string (GST_GL_VIDEO_CAPS)); - -beach: - - GST_DEBUG_OBJECT (visual, "returning caps %" GST_PTR_FORMAT, ret); - gst_object_unref (visual); - return ret; -} - -static gboolean -gst_visual_gl_src_setcaps (GstPad * pad, GstCaps * caps) -{ - GstVisualGL *visual = GST_VISUAL_GL (gst_pad_get_parent (pad)); - GstStructure *structure; - - structure = gst_caps_get_structure (caps, 0); - - GST_DEBUG_OBJECT (visual, "src pad got caps %" GST_PTR_FORMAT, caps); - - if (!gst_structure_get_int (structure, "width", &visual->width)) - goto error; - if (!gst_structure_get_int (structure, "height", &visual->height)) - goto error; - if (!gst_structure_get_fraction (structure, "framerate", &visual->fps_n, - &visual->fps_d)) - goto error; - - /* precalc some values */ - visual->spf = - gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n); - visual->duration = - gst_util_uint64_scale_int (GST_SECOND, visual->fps_d, visual->fps_n); - - gst_gl_display_gen_texture (visual->display, &visual->midtexture, - visual->width, visual->height); - - gst_gl_display_gen_fbo (visual->display, visual->width, visual->height, - &visual->fbo, &visual->depthbuffer); - - gst_object_unref (visual); - return TRUE; - - /* ERRORS */ -error: - { - GST_DEBUG_OBJECT (visual, "error parsing caps"); - gst_object_unref (visual); - return FALSE; - } -} - -static gboolean -gst_visual_gl_sink_setcaps (GstPad * pad, GstCaps * caps) -{ - GstVisualGL *visual = GST_VISUAL_GL (gst_pad_get_parent (pad)); - GstStructure *structure; - - structure = gst_caps_get_structure (caps, 0); - - gst_structure_get_int (structure, "channels", &visual->channels); - gst_structure_get_int (structure, "rate", &visual->rate); - - switch (visual->rate) { - case 8000: - visual->libvisual_rate = VISUAL_AUDIO_SAMPLE_RATE_8000; - break; - case 11250: - visual->libvisual_rate = VISUAL_AUDIO_SAMPLE_RATE_11250; - break; - case 22500: - visual->libvisual_rate = VISUAL_AUDIO_SAMPLE_RATE_22500; - break; - case 32000: - visual->libvisual_rate = VISUAL_AUDIO_SAMPLE_RATE_32000; - break; - case 44100: - visual->libvisual_rate = VISUAL_AUDIO_SAMPLE_RATE_44100; - break; - case 48000: - visual->libvisual_rate = VISUAL_AUDIO_SAMPLE_RATE_48000; - break; - case 96000: - visual->libvisual_rate = VISUAL_AUDIO_SAMPLE_RATE_96000; - break; - default: - gst_object_unref (visual); - return FALSE; - } - - /* this is how many samples we need to fill one frame at the requested - * framerate. */ - if (visual->fps_n != 0) { - visual->spf = - gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n); - } - visual->bps = visual->channels * sizeof (gint16); - - gst_object_unref (visual); - return TRUE; -} - -static gboolean -gst_vis_gl_src_negotiate (GstVisualGL * visual) -{ - GstCaps *othercaps, *target; - GstStructure *structure; - GstCaps *caps; - - caps = gst_pad_get_caps (visual->srcpad); - - /* see what the peer can do */ - othercaps = gst_pad_peer_get_caps (visual->srcpad); - if (othercaps) { - target = gst_caps_intersect (othercaps, caps); - gst_caps_unref (othercaps); - gst_caps_unref (caps); - - if (gst_caps_is_empty (target)) - goto no_format; - - gst_caps_truncate (target); - } else { - /* need a copy, we'll be modifying it when fixating */ - target = gst_caps_copy (caps); - gst_caps_unref (caps); - } - - /* fixate in case something is not fixed. This does nothing if the value is - * already fixed. For video we always try to fixate to something like - * 320x240x25 by convention. */ - structure = gst_caps_get_structure (target, 0); - gst_structure_fixate_field_nearest_int (structure, "width", DEFAULT_WIDTH); - gst_structure_fixate_field_nearest_int (structure, "height", DEFAULT_HEIGHT); - gst_structure_fixate_field_nearest_fraction (structure, "framerate", - DEFAULT_FPS_N, DEFAULT_FPS_D); - - gst_pad_set_caps (visual->srcpad, target); - gst_caps_unref (target); - - return TRUE; - - /* ERRORS */ -no_format: - { - GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL), - ("could not negotiate output format")); - gst_caps_unref (target); - return FALSE; - } -} - -static gboolean -gst_visual_gl_sink_event (GstPad * pad, GstEvent * event) -{ - GstVisualGL *visual; - gboolean res; - - visual = GST_VISUAL_GL (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_START: - res = gst_pad_push_event (visual->srcpad, event); - break; - case GST_EVENT_FLUSH_STOP: - /* reset QoS and adapter. */ - gst_visual_gl_reset (visual); - res = gst_pad_push_event (visual->srcpad, event); - break; - case GST_EVENT_NEWSEGMENT: - { - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - gboolean update; - - /* the newsegment values are used to clip the input samples - * and to convert the incomming timestamps to running time so - * we can do QoS */ - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - /* now configure the values */ - gst_segment_set_newsegment_full (&visual->segment, update, - rate, arate, format, start, stop, time); - - /* and forward */ - res = gst_pad_push_event (visual->srcpad, event); - break; - } - default: - res = gst_pad_push_event (visual->srcpad, event); - break; - } - - gst_object_unref (visual); - return res; -} - -static gboolean -gst_visual_gl_src_event (GstPad * pad, GstEvent * event) -{ - GstVisualGL *visual; - gboolean res; - - visual = GST_VISUAL_GL (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_QOS: - { - gdouble proportion; - GstClockTimeDiff diff; - GstClockTime timestamp; - - gst_event_parse_qos (event, &proportion, &diff, ×tamp); - - /* save stuff for the _chain function */ - GST_OBJECT_LOCK (visual); - visual->proportion = proportion; - if (diff >= 0) - /* we're late, this is a good estimate for next displayable - * frame (see part-qos.txt) */ - visual->earliest_time = timestamp + 2 * diff + visual->duration; - else - visual->earliest_time = timestamp + diff; - - GST_OBJECT_UNLOCK (visual); - - res = gst_pad_push_event (visual->sinkpad, event); - break; - } - default: - res = gst_pad_push_event (visual->sinkpad, event); - break; - } - - gst_object_unref (visual); - return res; -} - -static gboolean -gst_visual_gl_src_query (GstPad * pad, GstQuery * query) -{ - gboolean res; - GstVisualGL *visual; - - visual = GST_VISUAL_GL (gst_pad_get_parent (pad)); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_LATENCY: - { - /* We need to send the query upstream and add the returned latency to our - * own */ - GstClockTime min_latency, max_latency; - gboolean us_live; - GstClockTime our_latency; - guint max_samples; - - if ((res = gst_pad_peer_query (visual->sinkpad, query))) { - gst_query_parse_latency (query, &us_live, &min_latency, &max_latency); - - GST_DEBUG_OBJECT (visual, "Peer latency: min %" - GST_TIME_FORMAT " max %" GST_TIME_FORMAT, - GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency)); - - /* the max samples we must buffer buffer */ - max_samples = MAX (VISUAL_SAMPLES, visual->spf); - our_latency = - gst_util_uint64_scale_int (max_samples, GST_SECOND, visual->rate); - - GST_DEBUG_OBJECT (visual, "Our latency: %" GST_TIME_FORMAT, - GST_TIME_ARGS (our_latency)); - - /* we add some latency but only if we need to buffer more than what - * upstream gives us */ - min_latency += our_latency; - if (max_latency != -1) - max_latency += our_latency; - - GST_DEBUG_OBJECT (visual, "Calculated total latency : min %" - GST_TIME_FORMAT " max %" GST_TIME_FORMAT, - GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency)); - - gst_query_set_latency (query, TRUE, min_latency, max_latency); - } - break; - } - case GST_QUERY_CUSTOM: - { - GstStructure *structure = gst_query_get_structure (query); - gchar *name = gst_element_get_name (visual); - - res = g_strcmp0 (name, gst_structure_get_name (structure)) == 0; - g_free (name); - - if (!res) - res = gst_pad_query_default (pad, query); - break; - } - default: - res = gst_pad_peer_query (visual->sinkpad, query); - break; - } - - gst_object_unref (visual); - - return res; -} - -/* allocate and output buffer, if no format was negotiated, this - * function will negotiate one. After calling this function, a - * reverse negotiation could have happened. */ -static GstFlowReturn -get_buffer (GstVisualGL * visual, GstGLBuffer ** outbuf) -{ - /* we don't know an output format yet, pick one */ - if (GST_PAD_CAPS (visual->srcpad) == NULL) { - if (!gst_vis_gl_src_negotiate (visual)) - return GST_FLOW_NOT_NEGOTIATED; - } - - GST_DEBUG_OBJECT (visual, "allocating output buffer with caps %" - GST_PTR_FORMAT, GST_PAD_CAPS (visual->srcpad)); - - *outbuf = gst_gl_buffer_new (visual->display, visual->width, visual->height); - if (*outbuf == NULL) - return GST_FLOW_ERROR; - - gst_buffer_set_caps (GST_BUFFER (*outbuf), GST_PAD_CAPS (visual->srcpad)); - return GST_FLOW_OK; -} - -static void -actor_setup (GstGLDisplay * display, GstVisualGL * visual) -{ - /* save and clear top of the stack */ - glPushAttrib (GL_ALL_ATTRIB_BITS); - - glMatrixMode (GL_PROJECTION); - glPushMatrix (); - glLoadIdentity (); - - glMatrixMode (GL_MODELVIEW); - glPushMatrix (); - glLoadIdentity (); - - visual->actor_setup_result = visual_actor_realize (visual->actor); - if (visual->actor_setup_result == 0) { - /* store the actor's matrices for rendering the first frame */ - glGetDoublev (GL_MODELVIEW_MATRIX, visual->actor_modelview_matrix); - glGetDoublev (GL_PROJECTION_MATRIX, visual->actor_projection_matrix); - - visual->is_enabled_gl_depth_test = glIsEnabled (GL_DEPTH_TEST); - glGetIntegerv (GL_DEPTH_FUNC, &visual->gl_depth_func); - - visual->is_enabled_gl_blend = glIsEnabled (GL_BLEND); - glGetIntegerv (GL_BLEND_SRC_ALPHA, &visual->gl_blend_src_alpha); - - /* retore matrix */ - glMatrixMode (GL_PROJECTION); - glPopMatrix (); - - glMatrixMode (GL_MODELVIEW); - glPopMatrix (); - - glPopAttrib (); - } -} - -static void -actor_negotiate (GstGLDisplay * display, GstVisualGL * visual) -{ - gint err = VISUAL_OK; - - err = visual_video_set_depth (visual->video, VISUAL_VIDEO_DEPTH_GL); - if (err != VISUAL_OK) - g_warning ("failed to visual_video_set_depth\n"); - - err = - visual_video_set_dimension (visual->video, visual->width, visual->height); - if (err != VISUAL_OK) - g_warning ("failed to visual_video_set_dimension\n"); - - err = visual_actor_video_negotiate (visual->actor, 0, FALSE, FALSE); - if (err != VISUAL_OK) - g_warning ("failed to visual_actor_video_negotiate\n"); -} - -static void -check_gl_matrix (void) -{ - GLdouble projection_matrix[16]; - GLdouble modelview_matrix[16]; - gint i = 0; - gint j = 0; - - glGetDoublev (GL_PROJECTION_MATRIX, projection_matrix); - glGetDoublev (GL_MODELVIEW_MATRIX, modelview_matrix); - - for (j = 0; j < 4; ++j) { - for (i = 0; i < 4; ++i) { - if (projection_matrix[i + 4 * j] != projection_matrix[i + 4 * j]) - g_warning ("invalid projection matrix at coordiante %dx%d: %f\n", i, j, - projection_matrix[i + 4 * j]); - if (modelview_matrix[i + 4 * j] != modelview_matrix[i + 4 * j]) - g_warning ("invalid modelview_matrix matrix at coordiante %dx%d: %f\n", - i, j, modelview_matrix[i + 4 * j]); - } - } -} - -static void -render_frame (GstVisualGL * visual) -{ - const guint16 *data; - VisBuffer *lbuf, *rbuf; - guint16 ldata[VISUAL_SAMPLES], rdata[VISUAL_SAMPLES]; - guint i; - gcahr *name; - - /* Read VISUAL_SAMPLES samples per channel */ - data = - (const guint16 *) gst_adapter_peek (visual->adapter, - VISUAL_SAMPLES * visual->bps); - - lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL); - rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL); - - if (visual->channels == 2) { - for (i = 0; i < VISUAL_SAMPLES; i++) { - ldata[i] = *data++; - rdata[i] = *data++; - } - } else { - for (i = 0; i < VISUAL_SAMPLES; i++) { - ldata[i] = *data; - rdata[i] = *data++; - } - } - - visual_audio_samplepool_input_channel (visual->audio->samplepool, - lbuf, visual->libvisual_rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, - VISUAL_AUDIO_CHANNEL_LEFT); - visual_audio_samplepool_input_channel (visual->audio->samplepool, - rbuf, visual->libvisual_rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, - VISUAL_AUDIO_CHANNEL_RIGHT); - - visual_object_unref (VISUAL_OBJECT (lbuf)); - visual_object_unref (VISUAL_OBJECT (rbuf)); - - visual_audio_analyze (visual->audio); - - /* apply the matrices that the actor set up */ - glPushAttrib (GL_ALL_ATTRIB_BITS); - - glMatrixMode (GL_PROJECTION); - glPushMatrix (); - glLoadMatrixd (visual->actor_projection_matrix); - - glMatrixMode (GL_MODELVIEW); - glPushMatrix (); - glLoadMatrixd (visual->actor_modelview_matrix); - - /* This line try to hacks compatiblity with libprojectM - * If libprojectM version <= 2.0.0 then we have to unbind our current - * fbo to see something. But it's incorrect and we cannot use fbo chainning (append other glfilters - * after libvisual_gl_projectM will not work) - * To have full compatibility, libprojectM needs to take care of our fbo. - * Indeed libprojectM has to unbind it before the first rendering pass - * and then rebind it before the final pass. It's done from 2.0.1 - */ - name = gst_element_get_name (GST_ELEMENT (visual)); - if (g_ascii_strncasecmp (name, "visualglprojectm", 16) == 0 - && !HAVE_PROJECTM_TAKING_CARE_OF_EXTERNAL_FBO) - glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); - g_free (name); - - actor_negotiate (visual->display, visual); - - if (visual->is_enabled_gl_depth_test) { - glEnable (GL_DEPTH_TEST); - glDepthFunc (visual->gl_depth_func); - } - - if (visual->is_enabled_gl_blend) { - glEnable (GL_BLEND); - glBlendFunc (visual->gl_blend_src_alpha, GL_ZERO); - } - - visual_actor_run (visual->actor, visual->audio); - - check_gl_matrix (); - - glMatrixMode (GL_PROJECTION); - glPopMatrix (); - - glMatrixMode (GL_MODELVIEW); - glPopMatrix (); - - glPopAttrib (); - - glDisable (GL_DEPTH_TEST); - glDisable (GL_BLEND); - - /*glDisable (GL_LIGHT0); - glDisable (GL_LIGHTING); - glDisable (GL_POLYGON_OFFSET_FILL); - glDisable (GL_COLOR_MATERIAL); - glDisable (GL_CULL_FACE); */ - - GST_DEBUG_OBJECT (visual, "rendered one frame"); -} - -static void -bottom_up_to_top_down (gint width, gint height, guint texture, - GstVisualGL * visual) -{ - - glEnable (GL_TEXTURE_2D); - glBindTexture (GL_TEXTURE_2D, texture); - - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - - glBegin (GL_QUADS); - glTexCoord2i (0, 0); - glVertex2i (-1, 1); - glTexCoord2i (width, 0); - glVertex2i (1, 1); - glTexCoord2i (width, height); - glVertex2i (1, -1); - glTexCoord2i (0, height); - glVertex2i (-1, -1); - glEnd (); - - glBindTexture (GL_TEXTURE_2D, 0); - glDisable (GL_TEXTURE_2D); - - GST_DEBUG_OBJECT (visual, "bottom up to top down"); -} - -static GstFlowReturn -gst_visual_gl_chain (GstPad * pad, GstBuffer * buffer) -{ - GstGLBuffer *outbuf = NULL; - GstVisualGL *visual = GST_VISUAL_GL (gst_pad_get_parent (pad)); - GstFlowReturn ret = GST_FLOW_OK; - guint avail; - - GST_DEBUG_OBJECT (visual, "chain function called"); - - /* If we don't have an output format yet, preallocate a buffer to try and - * set one */ - if (GST_PAD_CAPS (visual->srcpad) == NULL) { - ret = get_buffer (visual, &outbuf); - if (ret != GST_FLOW_OK) { - gst_buffer_unref (buffer); - goto beach; - } - } - - /* resync on DISCONT */ - if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { - gst_adapter_clear (visual->adapter); - } - - GST_DEBUG_OBJECT (visual, - "Input buffer has %d samples, time=%" G_GUINT64_FORMAT, - GST_BUFFER_SIZE (buffer) / visual->bps, GST_BUFFER_TIMESTAMP (buffer)); - - gst_adapter_push (visual->adapter, buffer); - - while (TRUE) { - gboolean need_skip; - guint64 dist, timestamp; - - GST_DEBUG_OBJECT (visual, "processing buffer"); - - avail = gst_adapter_available (visual->adapter); - GST_DEBUG_OBJECT (visual, "avail now %u", avail); - - /* we need at least VISUAL_SAMPLES samples */ - if (avail < VISUAL_SAMPLES * visual->bps) - break; - - /* we need at least enough samples to make one frame */ - if (avail < visual->spf * visual->bps) - break; - - /* get timestamp of the current adapter byte */ - timestamp = gst_adapter_prev_timestamp (visual->adapter, &dist); - if (GST_CLOCK_TIME_IS_VALID (timestamp)) { - /* convert bytes to time */ - dist /= visual->bps; - timestamp += gst_util_uint64_scale_int (dist, GST_SECOND, visual->rate); - } - - if (timestamp != -1) { - gint64 qostime; - - /* QoS is done on running time */ - qostime = gst_segment_to_running_time (&visual->segment, GST_FORMAT_TIME, - timestamp); - qostime += visual->duration; - - GST_OBJECT_LOCK (visual); - /* check for QoS, don't compute buffers that are known to be late */ - need_skip = visual->earliest_time != -1 && - qostime <= visual->earliest_time; - GST_OBJECT_UNLOCK (visual); - - if (need_skip) { - GST_WARNING_OBJECT (visual, - "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT, - GST_TIME_ARGS (qostime), GST_TIME_ARGS (visual->earliest_time)); - goto skip; - } - } - - /* alloc a buffer if we don't have one yet, this happens - * when we pushed a buffer in this while loop before */ - if (outbuf == NULL) { - ret = get_buffer (visual, &outbuf); - if (ret != GST_FLOW_OK) { - goto beach; - } - } - - /* render libvisual plugin to our target */ - gst_gl_display_use_fbo_v2 (visual->display, - visual->width, visual->height, visual->fbo, visual->depthbuffer, - visual->midtexture, (GLCB_V2) render_frame, (gpointer *) visual); - - /* gst video is top-down whereas opengl plan is bottom up */ - gst_gl_display_use_fbo (visual->display, - visual->width, visual->height, visual->fbo, visual->depthbuffer, - outbuf->texture, (GLCB) bottom_up_to_top_down, - visual->width, visual->height, visual->midtexture, - 0, visual->width, 0, visual->height, GST_GL_DISPLAY_PROJECTION_ORTHO2D, - (gpointer *) visual); - - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - GST_BUFFER_DURATION (outbuf) = visual->duration; - - ret = gst_pad_push (visual->srcpad, GST_BUFFER (outbuf)); - outbuf = NULL; - - skip: - GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input", - visual->spf); - - /* Flush out the number of samples per frame */ - gst_adapter_flush (visual->adapter, visual->spf * visual->bps); - - /* quit the loop if something was wrong */ - if (ret != GST_FLOW_OK) - break; - } - -beach: - - if (outbuf != NULL) - gst_gl_buffer_unref (outbuf); - - gst_object_unref (visual); - - return ret; -} - -static GstStateChangeReturn -gst_visual_gl_change_state (GstElement * element, GstStateChange transition) -{ - GstVisualGL *visual = GST_VISUAL_GL (element); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - GstElement *parent = GST_ELEMENT (gst_element_get_parent (visual)); - GstStructure *structure = NULL; - GstQuery *query = NULL; - gboolean isPerformed = FALSE; - gchar *name; - - if (!parent) { - GST_ELEMENT_ERROR (visual, CORE, STATE_CHANGE, (NULL), - ("A parent bin is required")); - return FALSE; - } - - name = gst_element_get_name (visual); - structure = gst_structure_new (name, NULL); - query = gst_query_new_application (GST_QUERY_CUSTOM, structure); - g_free (name); - - isPerformed = gst_element_query (parent, query); - - if (isPerformed) { - const GValue *id_value = - gst_structure_get_value (structure, "gstgldisplay"); - if (G_VALUE_HOLDS_POINTER (id_value)) - /* at least one gl element is after in our gl chain */ - visual->display = - gst_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value))); - else { - /* this gl filter is a sink in terms of the gl chain */ - visual->display = gst_gl_display_new (); - gst_gl_display_create_context (visual->display, 0); - //TODO visual->external_gl_context); - } - - gst_visual_gl_reset (visual); - - visual->actor = - visual_actor_new (GST_VISUAL_GL_GET_CLASS (visual)->plugin->info-> - plugname); - visual->video = visual_video_new (); - visual->audio = visual_audio_new (); - - if (!visual->actor || !visual->video) - goto actor_setup_failed; - - gst_gl_display_thread_add (visual->display, - (GstGLDisplayThreadFunc) actor_setup, visual); - - if (visual->actor_setup_result != 0) - goto actor_setup_failed; - else - visual_actor_set_video (visual->actor, visual->video); - } - - gst_query_unref (query); - gst_object_unref (GST_OBJECT (parent)); - - if (!isPerformed) - return GST_STATE_CHANGE_FAILURE; - } - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - { - if (visual->fbo) { - gst_gl_display_del_fbo (visual->display, visual->fbo, - visual->depthbuffer); - visual->fbo = 0; - visual->depthbuffer = 0; - } - if (visual->midtexture) { - gst_gl_display_del_texture (visual->display, visual->midtexture, - visual->width, visual->height); - visual->midtexture = 0; - } - if (visual->display) { - gst_object_unref (visual->display); - visual->display = NULL; - } - - gst_visual_gl_clear_actors (visual); - } - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - - return ret; - - /* ERRORS */ -actor_setup_failed: - { - GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL), - ("could not set up actor")); - gst_visual_gl_clear_actors (visual); - return GST_STATE_CHANGE_FAILURE; - } -} - -static void -make_valid_name (char *name) -{ - /* - * Replace invalid chars with _ in the type name - */ - static const gchar extra_chars[] = "-_+"; - gchar *p = name; - - for (; *p; p++) { - int valid = ((p[0] >= 'A' && p[0] <= 'Z') || - (p[0] >= 'a' && p[0] <= 'z') || - (p[0] >= '0' && p[0] <= '9') || strchr (extra_chars, p[0])); - if (!valid) - *p = '_'; - } -} - -static gboolean -gst_visual_gl_actor_plugin_is_gl (VisObject * plugin, const gchar * name) -{ - gboolean is_gl; - gint depth; - - depth = VISUAL_ACTOR_PLUGIN (plugin)->vidoptions.depth; - is_gl = (depth & VISUAL_VIDEO_DEPTH_GL) != 0; - - if (!is_gl) { - GST_DEBUG ("plugin %s is not a GL plugin (%d), ignoring", name, depth); - } else { - GST_DEBUG ("plugin %s is a GL plugin (%d), registering", name, depth); - } - - return is_gl; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - guint i, count; - VisList *list; - - GST_DEBUG_CATEGORY_INIT (libvisual_debug, "libvisual", 0, - "libvisual audio visualisations"); - -#ifdef LIBVISUAL_PLUGINSBASEDIR - gst_plugin_add_dependency_simple (plugin, "HOME/.libvisual/actor", - LIBVISUAL_PLUGINSBASEDIR "/actor", NULL, GST_PLUGIN_DEPENDENCY_FLAG_NONE); -#endif - - visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_LOW); - visual_log_set_info_handler (libvisual_log_handler, (void *) GST_LEVEL_INFO); - visual_log_set_warning_handler (libvisual_log_handler, - (void *) GST_LEVEL_WARNING); - visual_log_set_critical_handler (libvisual_log_handler, - (void *) GST_LEVEL_ERROR); - visual_log_set_error_handler (libvisual_log_handler, - (void *) GST_LEVEL_ERROR); - - if (!visual_is_initialized ()) - if (visual_init (NULL, NULL) != 0) - return FALSE; - - list = visual_actor_get_list (); - - count = visual_collection_size (VISUAL_COLLECTION (list)); - - for (i = 0; i < count; i++) { - VisPluginRef *ref = visual_list_get (list, i); - VisPluginData *visplugin = NULL; - gboolean skip = FALSE; - GType type; - gchar *name; - GTypeInfo info = { - sizeof (GstVisualGLClass), - NULL, - NULL, - gst_visual_gl_class_init, - NULL, - ref, - sizeof (GstVisualGL), - 0, - NULL - }; - - visplugin = visual_plugin_load (ref); - - if (ref->info->plugname == NULL) - continue; - - /* Blacklist some plugins */ - if (strcmp (ref->info->plugname, "gstreamer") == 0 || - strcmp (ref->info->plugname, "gdkpixbuf") == 0) { - skip = TRUE; - } else { - /* only register plugins that support GL */ - skip = !(gst_visual_gl_actor_plugin_is_gl (visplugin->info->plugin, - visplugin->info->plugname)); - } - - visual_plugin_unload (visplugin); - - if (!skip) { - name = g_strdup_printf ("GstVisualGL%s", ref->info->plugname); - make_valid_name (name); - type = g_type_register_static (GST_TYPE_VISUAL_GL, name, &info, 0); - g_free (name); - - name = g_strdup_printf ("libvisual_gl_%s", ref->info->plugname); - make_valid_name (name); - if (!gst_element_register (plugin, name, GST_RANK_NONE, type)) { - g_free (name); - return FALSE; - } - g_free (name); - } - } - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "libvisual-gl", - "libvisual-gl visualization plugins", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/meson.build b/ext/meson.build index 62af78950..0eba7b49a 100644 --- a/ext/meson.build +++ b/ext/meson.build @@ -1,4 +1,3 @@ -#subdir('apexsink') subdir('assrender') #subdir('bs2b') subdir('bz2') @@ -25,13 +24,11 @@ subdir('kate') #subdir('ladspa') subdir('libde265') subdir('libmms') -#subdir('libvisual') #subdir('lv2') #subdir('modplug') #subdir('mpeg2enc') #subdir('mplex') #subdir('musepack') -#subdir('nas') #subdir('neon') #subdir('ofa') #subdir('openal') @@ -41,16 +38,13 @@ subdir('openh264') subdir('openjpeg') #subdir('openni2') subdir('opus') -#subdir('qt') subdir('resindvd') subdir('rsvg') subdir('rtmp') subdir('sbc') subdir('schroedinger') -#subdir('sdl') subdir('smoothstreaming') #subdir('sndfile') -#subdir('sndio') if cc.get_id() != 'msvc' # soundtouch doesn't do exporting of symbols for DLLs and I'm not sure how to # do that for C++ classes. -- Nirbheek @@ -62,7 +56,7 @@ endif #subdir('spc') subdir('srtp') #subdir('teletextdec') -#subdir('timidity') +#subdir('wildmidi') subdir('ttml') subdir('voaacenc') #subdir('voamrwbenc') @@ -71,5 +65,4 @@ subdir('wayland') #subdir('webrtcdsp') subdir('webp') subdir('x265') -#subdir('xvid') subdir('zbar') diff --git a/ext/nas/Makefile.am b/ext/nas/Makefile.am deleted file mode 100644 index ef1162abc..000000000 --- a/ext/nas/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -plugin_LTLIBRARIES = libgstnassink.la - -libgstnassink_la_SOURCES = nassink.c -libgstnassink_la_CFLAGS = \ - $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(NAS_CFLAGS) -libgstnassink_la_LIBADD = \ - $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_API_VERSION) $(NAS_LIBS) -libgstnassink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstnassink_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) - -noinst_HEADERS = nassink.h diff --git a/ext/nas/nassink.c b/ext/nas/nassink.c deleted file mode 100644 index 2d6404b8b..000000000 --- a/ext/nas/nassink.c +++ /dev/null @@ -1,583 +0,0 @@ -/* GStreamer - * Copyright (C) <2003> Laurent Vivier <Laurent.Vivier@bull.net> - * Copyright (C) <2004> Arwed v. Merkatz <v.merkatz@gmx.net> - * - * Based on esdsink.c: - * Copyright (C) <2001> Richard Boulton <richard-gst@tartarus.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 <gst/gst.h> -#include <string.h> -#include <audio/audiolib.h> -#include <audio/soundlib.h> -#include "nassink.h" - -#define NAS_SOUND_PORT_DURATION (2) - -GST_DEBUG_CATEGORY_STATIC (nas_debug); -#define GST_CAT_DEFAULT nas_debug - -enum -{ - ARG_0, - ARG_MUTE, - ARG_HOST -}; - -#define DEFAULT_MUTE FALSE -#define DEFAULT_HOST NULL - -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "endianness = (int) BYTE_ORDER, " - "signed = (boolean) TRUE, " - "width = (int) 16, " - "depth = (int) 16, " - "rate = (int) [ 1000, 96000 ], " - "channels = (int) [ 1, 2 ]; " - "audio/x-raw-int, " - "signed = (boolean) FALSE, " - "width = (int) 8, " - "depth = (int) 8, " - "rate = (int) [ 1000, 96000 ], " "channels = (int) [ 1, 2 ]") - ); - -static void gst_nas_sink_finalize (GObject * object); - -static gboolean gst_nas_sink_open (GstAudioSink * sink); -static gboolean gst_nas_sink_close (GstAudioSink * sink); -static gboolean gst_nas_sink_prepare (GstAudioSink * sink, - GstRingBufferSpec * spec); -static gboolean gst_nas_sink_unprepare (GstAudioSink * sink); -static guint gst_nas_sink_write (GstAudioSink * asink, gpointer data, - guint length); -static guint gst_nas_sink_delay (GstAudioSink * asink); -static void gst_nas_sink_reset (GstAudioSink * asink); -static GstCaps *gst_nas_sink_getcaps (GstBaseSink * pad); - -static void gst_nas_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_nas_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static void NAS_flush (GstNasSink * sink); -static void NAS_sendData (GstNasSink * sink, AuUint32 numBytes); -static AuBool NAS_EventHandler (AuServer * aud, AuEvent * ev, - AuEventHandlerRec * handler); -static AuDeviceID NAS_getDevice (AuServer * aud, int numTracks); - -GST_BOILERPLATE (GstNasSink, gst_nas_sink, GstAudioSink, GST_TYPE_AUDIO_SINK); - -static void -gst_nas_sink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_static_pad_template (element_class, &sink_factory); - gst_element_class_set_static_metadata (element_class, "NAS audio sink", - "Sink/Audio", - "Plays audio to a Network Audio Server", - "Laurent Vivier <Laurent.Vivier@bull.net>, " - "Arwed v. Merkatz <v.merkatz@gmx.net>"); -} - -static void -gst_nas_sink_class_init (GstNasSinkClass * klass) -{ - GObjectClass *gobject_class; - GstBaseSinkClass *gstbasesink_class; - GstAudioSinkClass *gstaudiosink_class; - - gobject_class = (GObjectClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstaudiosink_class = (GstAudioSinkClass *) klass; - - gobject_class->set_property = gst_nas_sink_set_property; - gobject_class->get_property = gst_nas_sink_get_property; - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_nas_sink_finalize); - - g_object_class_install_property (gobject_class, ARG_MUTE, - g_param_spec_boolean ("mute", "mute", "Whether to mute playback", - DEFAULT_MUTE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, ARG_HOST, - g_param_spec_string ("host", "host", - "host running the NAS daemon (name of X/Terminal, default is " - "$AUDIOSERVER or $DISPLAY)", DEFAULT_HOST, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - - gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_nas_sink_getcaps); - - gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_nas_sink_open); - gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_nas_sink_close); - gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_nas_sink_prepare); - gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_nas_sink_unprepare); - gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_nas_sink_write); - gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_nas_sink_delay); - gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_nas_sink_reset); -} - -static void -gst_nas_sink_init (GstNasSink * nassink, GstNasSinkClass * klass) -{ - /* properties will automatically be set to their default values */ - nassink->audio = NULL; - nassink->flow = AuNone; - nassink->need_data = 0; -} - -static void -gst_nas_sink_finalize (GObject * object) -{ - GstNasSink *nassink = GST_NAS_SINK (object); - - g_free (nassink->host); - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static GstCaps * -gst_nas_sink_getcaps (GstBaseSink * bsink) -{ - GstNasSink *nassink = GST_NAS_SINK (bsink); - const GstCaps *templatecaps; - AuServer *server; - GstCaps *fixated, *caps; - int i; - - server = nassink->audio; - - templatecaps = gst_static_pad_template_get_caps (&sink_factory); - - if (server == NULL) - return gst_caps_copy (templatecaps); - - fixated = gst_caps_copy (templatecaps); - for (i = 0; i < gst_caps_get_size (fixated); i++) { - GstStructure *structure; - gint min, max; - - min = AuServerMinSampleRate (server); - max = AuServerMaxSampleRate (server); - - structure = gst_caps_get_structure (fixated, i); - - if (min == max) - gst_structure_set (structure, "rate", G_TYPE_INT, max, NULL); - else - gst_structure_set (structure, "rate", GST_TYPE_INT_RANGE, min, max, NULL); - } - - caps = gst_caps_intersect (fixated, templatecaps); - gst_caps_unref (fixated); - - if (nassink->audio == NULL) - AuCloseServer (server); - - return caps; -} - -static gint -gst_nas_sink_sink_get_format (const GstRingBufferSpec * spec) -{ - gint result; - - switch (spec->format) { - case GST_U8: - result = AuFormatLinearUnsigned8; - break; - case GST_S8: - result = AuFormatLinearSigned8; - break; - case GST_S16_LE: - result = AuFormatLinearSigned16LSB; - break; - case GST_S16_BE: - result = AuFormatLinearSigned16MSB; - break; - case GST_U16_LE: - result = AuFormatLinearUnsigned16LSB; - break; - case GST_U16_BE: - result = AuFormatLinearUnsigned16MSB; - break; - default: - result = 0; - break; - } - return result; -} - -static gboolean -gst_nas_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) -{ - GstNasSink *sink = GST_NAS_SINK (asink); - AuElement elements[2]; - AuUint32 buf_samples; - unsigned char format; - - format = gst_nas_sink_sink_get_format (spec); - if (format == 0) { - GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL), - ("Unable to get format %d", spec->format)); - return FALSE; - } - GST_DEBUG_OBJECT (sink, "Format: %d %d\n", spec->format, format); - - sink->flow = AuGetScratchFlow (sink->audio, NULL); - if (sink->flow == 0) { - GST_DEBUG_OBJECT (sink, "couldn't get flow"); - return FALSE; - } - - buf_samples = spec->rate * NAS_SOUND_PORT_DURATION; - /* - spec->segsize = gst_util_uint64_scale (buf_samples * spec->bytes_per_sample, - spec->latency_time, GST_SECOND / GST_USECOND); - spec->segsize -= spec->segsize % spec->bytes_per_sample; - spec->segtotal = spec->buffer_time / spec->latency_time; - */ - spec->segsize = buf_samples * spec->bytes_per_sample; - spec->segtotal = 1; - - memset (spec->silence_sample, 0, spec->bytes_per_sample); - GST_DEBUG_OBJECT (sink, "Bytes per sample %d", spec->bytes_per_sample); - - GST_DEBUG_OBJECT (sink, "Rate %d Format %d tracks %d bufs %d %d/%d w %d", - spec->rate, format, spec->channels, (gint) buf_samples, spec->segsize, - spec->segtotal, spec->width); - AuMakeElementImportClient (&elements[0], /* element */ - spec->rate, /* rate */ - format, /* format */ - spec->channels, /* number of tracks */ - AuTrue, /* discart */ - buf_samples, /* max samples */ - (AuUint32) (buf_samples / 100 * AuSoundPortLowWaterMark), - /* low water mark */ - 0, /* num actions */ - NULL); - - sink->device = NAS_getDevice (sink->audio, spec->channels); - if (sink->device == AuNone) { - GST_DEBUG_OBJECT (sink, "no device with %i tracks found", spec->channels); - return FALSE; - } - - AuMakeElementExportDevice (&elements[1], /* element */ - 0, /* input */ - sink->device, /* device */ - spec->rate, /* rate */ - AuUnlimitedSamples, /* num samples */ - 0, /* num actions */ - NULL); /* actions */ - - AuSetElements (sink->audio, /* server */ - sink->flow, /* flow ID */ - AuTrue, /* clocked */ - 2, /* num elements */ - elements, /* elements */ - NULL); - - AuRegisterEventHandler (sink->audio, /* server */ - AuEventHandlerIDMask, /* value mask */ - 0, /* type */ - sink->flow, /* flow ID */ - NAS_EventHandler, /* callback */ - (AuPointer) sink); /* data */ - - AuStartFlow (sink->audio, sink->flow, NULL); - - return TRUE; -} - -static gboolean -gst_nas_sink_unprepare (GstAudioSink * asink) -{ - GstNasSink *sink = GST_NAS_SINK (asink); - - if (sink->flow != AuNone) { - AuBool clocked; - int num_elements; - AuStatus status; - AuElement *oldelems; - - GST_DEBUG_OBJECT (sink, "flushing buffer"); - NAS_flush (sink); - - oldelems = - AuGetElements (sink->audio, sink->flow, &clocked, &num_elements, - &status); - if (num_elements > 0) { - GST_DEBUG_OBJECT (sink, "GetElements status: %i", status); - if (oldelems) - AuFreeElements (sink->audio, num_elements, oldelems); - } - - AuStopFlow (sink->audio, sink->flow, NULL); - AuReleaseScratchFlow (sink->audio, sink->flow, NULL); - sink->flow = AuNone; - } - sink->need_data = 0; - - return TRUE; -} - -static guint -gst_nas_sink_delay (GstAudioSink * asink) -{ - GST_DEBUG_OBJECT (asink, "nas_sink_delay"); - return 0; -} - -static void -gst_nas_sink_reset (GstAudioSink * asink) -{ - GstNasSink *sink = GST_NAS_SINK (asink); - - GST_DEBUG_OBJECT (sink, "reset"); - - if (sink->flow != AuNone) - AuStopFlow (sink->audio, sink->flow, NULL); -} - -static guint -gst_nas_sink_write (GstAudioSink * asink, gpointer data, guint length) -{ - GstNasSink *nassink = GST_NAS_SINK (asink); - int used = 0; - - NAS_flush (nassink); - if (!nassink->mute && nassink->audio != NULL && nassink->flow != AuNone) { - - if (nassink->need_data == 0) - return 0; - - used = nassink->need_data > length ? length : nassink->need_data; - AuWriteElement (nassink->audio, nassink->flow, 0, used, data, AuFalse, - NULL); - nassink->need_data -= used; - if (used == length) - AuSync (nassink->audio, AuFalse); - } else - used = length; - return used; -} - -static void -gst_nas_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstNasSink *nassink; - - nassink = GST_NAS_SINK (object); - - switch (prop_id) { - case ARG_MUTE: - nassink->mute = g_value_get_boolean (value); - break; - case ARG_HOST: - g_free (nassink->host); - nassink->host = g_value_dup_string (value); - if (nassink->host == NULL) - nassink->host = g_strdup (g_getenv ("AUDIOSERVER")); - if (nassink->host == NULL) - nassink->host = g_strdup (g_getenv ("DISPLAY")); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_nas_sink_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstNasSink *nassink; - - nassink = GST_NAS_SINK (object); - - switch (prop_id) { - case ARG_MUTE: - g_value_set_boolean (value, nassink->mute); - break; - case ARG_HOST: - g_value_set_string (value, nassink->host); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -gst_nas_sink_open (GstAudioSink * asink) -{ - GstNasSink *sink = GST_NAS_SINK (asink); - - GST_DEBUG_OBJECT (sink, "opening, host = '%s'", GST_STR_NULL (sink->host)); - - /* Open Server */ - sink->audio = AuOpenServer (sink->host, 0, NULL, 0, NULL, NULL); - if (sink->audio == NULL) { - GST_DEBUG_OBJECT (sink, "opening failed"); - return FALSE; - } - sink->flow = AuNone; - sink->need_data = 0; - - /* Start a flow */ - GST_DEBUG_OBJECT (asink, "opened audio device"); - return TRUE; -} - -static gboolean -gst_nas_sink_close (GstAudioSink * asink) -{ - GstNasSink *sink = GST_NAS_SINK (asink); - - if (sink->audio) { - AuCloseServer (sink->audio); - sink->audio = NULL; - } - - GST_DEBUG_OBJECT (sink, "closed audio device"); - return TRUE; -} - -static void -NAS_flush (GstNasSink * sink) -{ - AuEvent ev; - - AuNextEvent (sink->audio, AuTrue, &ev); - AuDispatchEvent (sink->audio, &ev); -} - -static void -NAS_sendData (GstNasSink * sink, AuUint32 numBytes) -{ - sink->need_data += numBytes; - return; -} - -static AuBool -NAS_EventHandler (AuServer * aud, AuEvent * ev, AuEventHandlerRec * handler) -{ - GstNasSink *sink = (GstNasSink *) handler->data; - AuElementNotifyEvent *notify; - - switch (ev->type) { - - case AuEventTypeElementNotify: - - notify = (AuElementNotifyEvent *) ev; - - switch (notify->kind) { - - case AuElementNotifyKindLowWater: - NAS_sendData (sink, notify->num_bytes); - break; - - case AuElementNotifyKindState: - - switch (notify->cur_state) { - - case AuStateStop: - - if (sink->flow != AuNone) { - if (notify->reason == AuReasonEOF) - AuStopFlow (handler->aud, sink->flow, NULL); - AuReleaseScratchFlow (handler->aud, sink->flow, NULL); - sink->flow = AuNone; - } - AuUnregisterEventHandler (handler->aud, handler); - break; - - case AuStatePause: - - switch (notify->reason) { - case AuReasonUnderrun: - case AuReasonOverrun: - case AuReasonEOF: - case AuReasonWatermark: - - NAS_sendData (sink, notify->num_bytes); - - break; - - case AuReasonHardware: - - if (AuSoundRestartHardwarePauses) - AuStartFlow (handler->aud, sink->flow, NULL); - else - AuStopFlow (handler->aud, sink->flow, NULL); - - break; - } - break; - } - break; - } - break; - } - - return AuTrue; -} - -static AuDeviceID -NAS_getDevice (AuServer * aud, int numTracks) -{ - int i; - - for (i = 0; i < AuServerNumDevices (aud); i++) { - if ((AuDeviceKind (AuServerDevice (aud, i)) - == AuComponentKindPhysicalOutput) && - (AuDeviceNumTracks (AuServerDevice (aud, i)) == numTracks)) { - - return AuDeviceIdentifier (AuServerDevice (aud, i)); - - } - } - - return AuNone; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - GST_DEBUG_CATEGORY_INIT (nas_debug, "NAS", 0, NULL); - - if (!gst_element_register (plugin, "nassink", GST_RANK_NONE, - GST_TYPE_NAS_SINK)) { - return FALSE; - } - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - nas, - "NAS (Network Audio System) support for GStreamer", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/ext/nas/nassink.h b/ext/nas/nassink.h deleted file mode 100644 index 14ab5fd93..000000000 --- a/ext/nas/nassink.h +++ /dev/null @@ -1,72 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef __GST_NAS_SINK_H__ -#define __GST_NAS_SINK_H__ - -#include <gst/gst.h> -#include <gst/audio/gstaudiosink.h> - -G_BEGIN_DECLS - -#define GST_TYPE_NAS_SINK \ - (gst_nas_sink_get_type()) -#define GST_NAS_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NAS_SINK,GstNasSink)) -#define GST_NAS_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NAS_SINK,GstNasSinkClass)) -#define GST_IS_NAS_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NAS_SINK)) -#define GST_IS_NAS_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NAS_SINK)) - -typedef struct _GstNasSink GstNasSink; -typedef struct _GstNasSinkClass GstNasSinkClass; - -struct _GstNasSink { - GstAudioSink audiosink; - - /*< private >*/ - - /* instance properties */ - - gboolean mute; - gchar* host; - - /* Server info */ - - AuServer *audio; - AuFlowID flow; - AuDeviceID device; - - /* buffer */ - - AuUint32 need_data; -}; - -struct _GstNasSinkClass { - GstAudioSinkClass parent_class; -}; - -GType gst_nas_sink_get_type(void); - -G_END_DECLS - -#endif /* __GST_NAS_SINK_H__ */ diff --git a/ext/sdl/Makefile.am b/ext/sdl/Makefile.am deleted file mode 100644 index d0c5b1a95..000000000 --- a/ext/sdl/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -plugin_LTLIBRARIES = libgstsdl.la - -libgstsdl_la_SOURCES = \ - gstsdl.c \ - sdlvideosink.c \ - sdlaudiosink.c - -libgstsdl_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(SDL_CFLAGS) -libgstsdl_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \ - -lgstvideo-$(GST_API_VERSION) \ - -lgstaudio-$(GST_API_VERSION) \ - -lgstinterfaces-$(GST_API_VERSION) \ - $(SDL_LIBS) -libgstsdl_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstsdl_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) - -noinst_HEADERS = \ - sdlvideosink.h \ - sdlaudiosink.h diff --git a/ext/sdl/gstsdl.c b/ext/sdl/gstsdl.c deleted file mode 100644 index 8813edb95..000000000 --- a/ext/sdl/gstsdl.c +++ /dev/null @@ -1,45 +0,0 @@ -/* GStreamer - * Copyright (C) <2005> Edgard Lima <edgard.lima@indt.org.br> - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "sdlvideosink.h" -#include "sdlaudiosink.h" - - -GST_DEBUG_CATEGORY (sdl_debug); - -static gboolean -plugin_init (GstPlugin * plugin) -{ - - if (!gst_element_register (plugin, "sdlvideosink", GST_RANK_NONE, - GST_TYPE_SDLVIDEOSINK) || - !gst_element_register (plugin, "sdlaudiosink", GST_RANK_NONE, - GST_TYPE_SDLAUDIOSINK)) { - return FALSE; - } - - GST_DEBUG_CATEGORY_INIT (sdl_debug, "sdl", 0, "SDL elements"); - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - sdl, - "SDL (Simple DirectMedia Layer) support for GStreamer", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/sdl/sdlaudiosink.c b/ext/sdl/sdlaudiosink.c deleted file mode 100644 index ff03782d1..000000000 --- a/ext/sdl/sdlaudiosink.c +++ /dev/null @@ -1,439 +0,0 @@ -/* GStreamer - * Copyright (C) <2005> Edgard Lima <edgard.lima@indt.org.br> - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "sdlaudiosink.h" - -#include <SDL_byteorder.h> -#include <string.h> - -#include <unistd.h> - -#include <gst/glib-compat-private.h> - -GST_DEBUG_CATEGORY_EXTERN (sdl_debug); -#define GST_CAT_DEFAULT sdl_debug - -static void gst_sdlaudio_sink_dispose (GObject * object); - -static GstCaps *gst_sdlaudio_sink_getcaps (GstBaseSink * bsink); - -static gboolean gst_sdlaudio_sink_open (GstAudioSink * asink); -static gboolean gst_sdlaudio_sink_close (GstAudioSink * asink); -static gboolean gst_sdlaudio_sink_prepare (GstAudioSink * asink, - GstRingBufferSpec * spec); -static gboolean gst_sdlaudio_sink_unprepare (GstAudioSink * asink); -static guint gst_sdlaudio_sink_write (GstAudioSink * asink, gpointer data, - guint length); - -#if 0 -static guint gst_sdlaudio_sink_delay (GstAudioSink * asink); -static void gst_sdlaudio_sink_reset (GstAudioSink * asink); -#endif - - -/* SdlaudioSink signals and args */ -enum -{ - LAST_SIGNAL -}; - -#define SEMAPHORE_INIT(s,f) \ - do { \ - s.cond = g_cond_new(); \ - s.mutex = g_mutex_new(); \ - s.mutexflag = f; \ - } while(0) - -#define SEMAPHORE_CLOSE(s) \ - do { \ - if ( s.cond ) { \ - g_cond_free(s.cond); \ - s.cond = NULL; \ - } \ - if ( s.mutex ) { \ - g_mutex_free(s.mutex); \ - s.mutex = NULL; \ - } \ - } while(0) - -#define SEMAPHORE_UP(s) \ - do \ - { \ - g_mutex_lock(s.mutex); \ - s.mutexflag = TRUE; \ - g_mutex_unlock(s.mutex); \ - g_cond_signal(s.cond); \ - } while(0) - -#define SEMAPHORE_DOWN(s, e) \ - do \ - { \ - while (1) { \ - g_mutex_lock(s.mutex); \ - if (!s.mutexflag) { \ - if ( e ) { \ - g_mutex_unlock(s.mutex); \ - break; \ - } \ - g_cond_wait(s.cond,s.mutex); \ - } \ - else { \ - s.mutexflag = FALSE; \ - g_mutex_unlock(s.mutex); \ - break; \ - } \ - g_mutex_unlock(s.mutex); \ - } \ - } while(0) - - -static GstStaticPadTemplate sdlaudiosink_sink_factory = - GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, " - "signed = (boolean) { TRUE, FALSE }, " - "width = (int) 16, " - "depth = (int) 16, " - "rate = (int) [ 1, MAX ], " - "channels = (int) [ 1, 2 ]; " - "audio/x-raw-int, " - "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, " - "signed = (boolean) { TRUE, FALSE }, " - "width = (int) 8, " - "depth = (int) 8, " - "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]") - ); - -GST_BOILERPLATE (GstSDLAudioSink, gst_sdlaudio_sink, GstAudioSink, - GST_TYPE_AUDIO_SINK); - -static void -gst_sdlaudio_sink_dispose (GObject * object) -{ - GstSDLAudioSink *sdlaudiosink = GST_SDLAUDIOSINK (object); - - SEMAPHORE_CLOSE (sdlaudiosink->semB); - - SEMAPHORE_CLOSE (sdlaudiosink->semA); - - if (sdlaudiosink->buffer) { - g_free (sdlaudiosink->buffer); - } - - G_OBJECT_CLASS (parent_class)->dispose (object); - -} - -static void -gst_sdlaudio_sink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_static_metadata (element_class, "SDL audio sink", - "Sink/Audio", - "Output to a sound card via SDLAUDIO", - "Edgard Lima <edgard.lima@indt.org.br>"); - - gst_element_class_add_static_pad_template (element_class, - &sdlaudiosink_sink_factory); -} - -static void -gst_sdlaudio_sink_class_init (GstSDLAudioSinkClass * klass) -{ - GObjectClass *gobject_class; - GstBaseSinkClass *gstbasesink_class; - GstAudioSinkClass *gstaudiosink_class; - - gobject_class = (GObjectClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstaudiosink_class = (GstAudioSinkClass *) klass; - - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_dispose); - - gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_getcaps); - - gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_open); - gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_close); - gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_prepare); - gstaudiosink_class->unprepare = - GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_unprepare); - gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_write); - -#if 0 - gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_delay); - gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_sdlaudio_sink_reset); -#endif - -} - -static void -gst_sdlaudio_sink_init (GstSDLAudioSink * sdlaudiosink, - GstSDLAudioSinkClass * g_class) -{ - GST_DEBUG ("initializing sdlaudiosink"); - - memset (&sdlaudiosink->fmt, 0, sizeof (SDL_AudioSpec)); - - sdlaudiosink->buffer = NULL; - sdlaudiosink->eos = FALSE; - - SEMAPHORE_INIT (sdlaudiosink->semA, TRUE); - - SEMAPHORE_INIT (sdlaudiosink->semB, FALSE); - -} - -static GstCaps * -gst_sdlaudio_sink_getcaps (GstBaseSink * bsink) -{ - return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD - (bsink))); -} - -static gint -gst_sdlaudio_sink_get_format (GstBufferFormat fmt) -{ - gint result = GST_UNKNOWN; - - switch (fmt) { - case GST_U8: - result = AUDIO_U8; - break; - case GST_S8: - result = AUDIO_S8; - break; - case GST_S16_LE: - result = AUDIO_S16LSB; - break; - case GST_S16_BE: - result = AUDIO_S16MSB; - break; - case GST_U16_LE: - result = AUDIO_U16LSB; - break; - case GST_U16_BE: - result = AUDIO_U16MSB; - break; - default: - break; - } - return result; -} - -static gboolean -gst_sdlaudio_sink_open (GstAudioSink * asink) -{ - GstSDLAudioSink *sdlaudio; - - sdlaudio = GST_SDLAUDIOSINK (asink); - - if (SDL_Init (SDL_INIT_AUDIO) < 0) { - goto open_failed; - } - - return TRUE; - -open_failed: - { - GST_ELEMENT_ERROR (sdlaudio, LIBRARY, INIT, - ("Unable to init SDL: %s\n", SDL_GetError ()), (NULL)); - return FALSE; - } -} - -static gboolean -gst_sdlaudio_sink_close (GstAudioSink * asink) -{ - GstSDLAudioSink *sdlaudio = GST_SDLAUDIOSINK (asink); - - sdlaudio->eos = TRUE; - SEMAPHORE_UP (sdlaudio->semA); - SEMAPHORE_UP (sdlaudio->semB); - SDL_QuitSubSystem (SDL_INIT_AUDIO); - return TRUE; -} - -static guint -gst_sdlaudio_sink_write (GstAudioSink * asink, gpointer data, guint length) -{ - GstSDLAudioSink *sdlaudio = GST_SDLAUDIOSINK (asink); - - if (sdlaudio->fmt.size != length) { - GST_ERROR ("ring buffer segment length (%u) != sdl buffer len (%u)", length, - sdlaudio->fmt.size); - } - - SEMAPHORE_DOWN (sdlaudio->semA, sdlaudio->eos); - - if (!sdlaudio->eos) - memcpy (sdlaudio->buffer, data, length); - - SEMAPHORE_UP (sdlaudio->semB); - - return sdlaudio->fmt.size; -} - - -static void -mixaudio (void *unused, Uint8 * stream, int len) -{ - GstSDLAudioSink *sdlaudio; - - sdlaudio = GST_SDLAUDIOSINK (unused); - - if (sdlaudio->fmt.size != len) { - GST_ERROR ("fmt buffer len (%u) != sdl callback len (%d)", - sdlaudio->fmt.size, len); - } - - SEMAPHORE_DOWN (sdlaudio->semB, sdlaudio->eos); - - if (!sdlaudio->eos) - SDL_MixAudio (stream, sdlaudio->buffer, sdlaudio->fmt.size, - SDL_MIX_MAXVOLUME); - - SEMAPHORE_UP (sdlaudio->semA); - -} - -static gboolean -gst_sdlaudio_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) -{ - GstSDLAudioSink *sdlaudio; - gint power2 = -1; - - sdlaudio = GST_SDLAUDIOSINK (asink); - - sdlaudio->fmt.format = gst_sdlaudio_sink_get_format (spec->format); - if (sdlaudio->fmt.format == 0) - goto wrong_format; - - if (spec->width != 16 && spec->width != 8) - goto dodgy_width; - - sdlaudio->fmt.freq = spec->rate; - sdlaudio->fmt.channels = spec->channels; - sdlaudio->fmt.samples = - spec->segsize / (spec->channels * ((sdlaudio->fmt.format & 0xFF) >> 3)); - sdlaudio->fmt.callback = mixaudio; - sdlaudio->fmt.userdata = sdlaudio; - - GST_DEBUG ("set segsize: %d, segtotal: %d, samples: %d", spec->segsize, - spec->segtotal, sdlaudio->fmt.samples); - - while (sdlaudio->fmt.samples) { - sdlaudio->fmt.samples >>= 1; - ++power2; - } - - sdlaudio->fmt.samples = 1; - sdlaudio->fmt.samples <<= power2; - - GST_DEBUG ("set segsize: %d, segtotal: %d, samples: %d", spec->segsize, - spec->segtotal, sdlaudio->fmt.samples); - - if (SDL_OpenAudio (&sdlaudio->fmt, NULL) < 0) { - goto unable_open; - } - - spec->segsize = sdlaudio->fmt.size; - - sdlaudio->buffer = g_malloc (sdlaudio->fmt.size); - memset (sdlaudio->buffer, sdlaudio->fmt.silence, sdlaudio->fmt.size); - - GST_DEBUG ("set segsize: %d, segtotal: %d, samples: %d", spec->segsize, - spec->segtotal, sdlaudio->fmt.samples); - - spec->bytes_per_sample = - spec->channels * ((sdlaudio->fmt.format & 0xFF) >> 3); - memset (spec->silence_sample, sdlaudio->fmt.silence, spec->bytes_per_sample); - - SDL_PauseAudio (0); - - return TRUE; - -unable_open: - { - GST_ELEMENT_ERROR (sdlaudio, RESOURCE, OPEN_READ, - ("Unable to open audio: %s", SDL_GetError ()), (NULL)); - return FALSE; - } -wrong_format: - { - GST_ELEMENT_ERROR (sdlaudio, RESOURCE, OPEN_READ, - ("Unable to get format %d", spec->format), (NULL)); - return FALSE; - } -dodgy_width: - { - GST_ELEMENT_ERROR (sdlaudio, RESOURCE, OPEN_READ, - ("unexpected width %d", spec->width), (NULL)); - return FALSE; - } -} - -static gboolean -gst_sdlaudio_sink_unprepare (GstAudioSink * asink) -{ - - SDL_CloseAudio (); - - return TRUE; - -#if 0 - if (!gst_sdlaudio_sink_close (asink)) - goto couldnt_close; - - if (!gst_sdlaudio_sink_open (asink)) - goto couldnt_reopen; - - return TRUE; - -couldnt_close: - { - GST_DEBUG ("Could not close the audio device"); - return FALSE; - } -couldnt_reopen: - { - GST_DEBUG ("Could not reopen the audio device"); - return FALSE; - } -#endif - -} - -#if 0 -static guint -gst_sdlaudio_sink_delay (GstAudioSink * asink) -{ - GstSDLAudioSink *sdlaudio; - - sdlaudio = GST_SDLAUDIOSINK (asink); - - return 0; -} - -static void -gst_sdlaudio_sink_reset (GstAudioSink * asink) -{ -} -#endif diff --git a/ext/sdl/sdlaudiosink.h b/ext/sdl/sdlaudiosink.h deleted file mode 100644 index 8532f3ffd..000000000 --- a/ext/sdl/sdlaudiosink.h +++ /dev/null @@ -1,65 +0,0 @@ -/* GStreamer - * Copyright (C) <2005> Edgard Lima <edgard.lima@indt.org.br> - * - * 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 - */ - -#ifndef __GST_SDLAUDIOSINK_H__ -#define __GST_SDLAUDIOSINK_H__ - - -#include <gst/gst.h> -#include <gst/audio/gstaudiosink.h> - -#include <SDL.h> -#include <SDL_audio.h> - -G_BEGIN_DECLS - -#define GST_TYPE_SDLAUDIOSINK (gst_sdlaudio_sink_get_type()) -#define GST_SDLAUDIOSINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SDLAUDIOSINK,GstSDLAudioSink)) -#define GST_SDLAUDIOSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SDLAUDIOSINK,GstSDLAudioSinkClass)) -#define GST_IS_SDLAUDIOSINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SDLAUDIOSINK)) -#define GST_IS_SDLAUDIOSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SDLAUDIOSINK)) - -typedef struct _GstSDLAudioSink GstSDLAudioSink; -typedef struct _GstSDLAudioSinkClass GstSDLAudioSinkClass; - -typedef struct _gstsdl_semaphore { - GCond *cond; - GMutex *mutex; - gboolean mutexflag; - -} gstsdl_semaphore; - -struct _GstSDLAudioSink { - GstAudioSink sink; - - SDL_AudioSpec fmt; - guint8 *buffer; - - gstsdl_semaphore semA; - - gstsdl_semaphore semB; - - gboolean eos; - -}; - -struct _GstSDLAudioSinkClass { - GstAudioSinkClass parent_class; -}; - -GType gst_sdlaudio_sink_get_type(void); - -G_END_DECLS - -#endif /* __GST_SDLAUDIOSINK_H__ */ diff --git a/ext/sdl/sdlvideosink.c b/ext/sdl/sdlvideosink.c deleted file mode 100644 index 7f05dcad8..000000000 --- a/ext/sdl/sdlvideosink.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* GStreamer SDL plugin - * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * 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. - */ - -/* let's not forget to mention that all this was based on aasink ;-) */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <signal.h> -#include <string.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <stdlib.h> - -#include <gst/glib-compat-private.h> -#include <gst/interfaces/xoverlay.h> -#include <gst/interfaces/navigation.h> - -#include "sdlvideosink.h" - -GST_DEBUG_CATEGORY_EXTERN (sdl_debug); -#define GST_CAT_DEFAULT sdl_debug - -/* These macros are adapted from videotestsrc.c - * and/or gst-plugins/gst/games/gstvideoimage.c */ -#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width)) -#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2) -#define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2) - -#define I420_Y_OFFSET(w,h) (0) -#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h))) -#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) - -#define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) - - -enum -{ - PROP_0, - PROP_FULLSCREEN -}; - -static void gst_sdlvideosink_interface_init (GstImplementsInterfaceClass * - klass); -static gboolean gst_sdlvideosink_supported (GstImplementsInterface * iface, - GType type); - -static void gst_sdlvideosink_xoverlay_init (GstXOverlayClass * klass); -static void gst_sdlvideosink_xoverlay_set_window_handle - (GstXOverlay * overlay, guintptr parent); - -static gboolean gst_sdlvideosink_lock (GstSDLVideoSink * sdl); -static void gst_sdlvideosink_unlock (GstSDLVideoSink * sdl); - -static gboolean gst_sdlvideosink_initsdl (GstSDLVideoSink * sdl); -static void gst_sdlvideosink_deinitsdl (GstSDLVideoSink * sdl); - -static gboolean gst_sdlvideosink_create (GstSDLVideoSink * sdl); -static void gst_sdlvideosink_destroy (GstSDLVideoSink * sdl); - -static gboolean gst_sdlvideosink_setcaps (GstBaseSink * bsink, GstCaps * caps); - -static GstFlowReturn gst_sdlvideosink_show_frame (GstBaseSink * bsink, - GstBuffer * buff); - -static void gst_sdlvideosink_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_sdlvideosink_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); -static GstStateChangeReturn -gst_sdlvideosink_change_state (GstElement * element, GstStateChange transition); - -static void gst_sdlvideosink_navigation_init (GstNavigationInterface * iface); - -static void gst_sdlv_process_events (GstSDLVideoSink * sdlvideosink); - -static GstPadTemplate *sink_template; - -static void -_do_init (GType type) -{ - static const GInterfaceInfo iface_info = { - (GInterfaceInitFunc) gst_sdlvideosink_interface_init, - NULL, - NULL, - }; - static const GInterfaceInfo xoverlay_info = { - (GInterfaceInitFunc) gst_sdlvideosink_xoverlay_init, - NULL, - NULL, - }; - static const GInterfaceInfo navigation_info = { - (GInterfaceInitFunc) gst_sdlvideosink_navigation_init, - NULL, - NULL, - }; - - g_type_add_interface_static (type, - GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info); - g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &xoverlay_info); - g_type_add_interface_static (type, GST_TYPE_NAVIGATION, &navigation_info); - -} - -GST_BOILERPLATE_FULL (GstSDLVideoSink, gst_sdlvideosink, GstVideoSink, - GST_TYPE_VIDEO_SINK, _do_init); - -static void -gst_sdlvideosink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GstCaps *capslist; - gint i; - guint32 formats[] = { - GST_MAKE_FOURCC ('I', '4', '2', '0'), - GST_MAKE_FOURCC ('Y', 'V', '1', '2'), - GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), - GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'), - GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') - }; - - /* make a list of all available caps */ - capslist = gst_caps_new_empty (); - for (i = 0; i < G_N_ELEMENTS (formats); i++) { - gst_caps_append_structure (capslist, - gst_structure_new ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, formats[i], - "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1, NULL)); - } - - sink_template = gst_pad_template_new ("sink", - GST_PAD_SINK, GST_PAD_ALWAYS, capslist); - - gst_element_class_add_pad_template (element_class, sink_template); - gst_element_class_set_static_metadata (element_class, "SDL video sink", - "Sink/Video", "An SDL-based videosink", - "Ronald Bultje <rbultje@ronald.bitfreak.net>, " - "Edgard Lima <edgard.lima@indt.org.br>, " - "Jan Schmidt <thaytan@mad.scientist.com>"); -} - -static void -gst_sdlvideosink_finalize (GObject * obj) -{ - g_mutex_free (GST_SDLVIDEOSINK (obj)->lock); - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -gst_sdlvideosink_get_times (GstBaseSink * basesink, GstBuffer * buffer, - GstClockTime * start, GstClockTime * end) -{ - GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (basesink); - GstClockTime timestamp, duration; - - timestamp = GST_BUFFER_TIMESTAMP (buffer); - if (GST_CLOCK_TIME_IS_VALID (timestamp)) { - *start = timestamp; - duration = GST_BUFFER_DURATION (buffer); - if (GST_CLOCK_TIME_IS_VALID (duration)) { - *end = timestamp + duration; - } else { - if (sdlvideosink->framerate_n > 0) { - *end = timestamp + - gst_util_uint64_scale_int (GST_SECOND, sdlvideosink->framerate_d, - sdlvideosink->framerate_n); - } - } - } -} - -static void -gst_sdlvideosink_class_init (GstSDLVideoSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstvs_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstvs_class = (GstBaseSinkClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->set_property = gst_sdlvideosink_set_property; - gobject_class->get_property = gst_sdlvideosink_get_property; - - gobject_class->finalize = gst_sdlvideosink_finalize; - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_sdlvideosink_change_state); - - gstvs_class->set_caps = GST_DEBUG_FUNCPTR (gst_sdlvideosink_setcaps); - gstvs_class->get_times = GST_DEBUG_FUNCPTR (gst_sdlvideosink_get_times); - gstvs_class->preroll = GST_DEBUG_FUNCPTR (gst_sdlvideosink_show_frame); - gstvs_class->render = GST_DEBUG_FUNCPTR (gst_sdlvideosink_show_frame); - - g_object_class_install_property (gobject_class, PROP_FULLSCREEN, - g_param_spec_boolean ("fullscreen", "Fullscreen", - "If true it will be Full screen", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /*gstvs_class->set_video_out = gst_sdlvideosink_set_video_out; - gstvs_class->push_ui_event = gst_sdlvideosink_push_ui_event; - gstvs_class->set_geometry = gst_sdlvideosink_set_geometry; */ -} - -#if 0 -/* FIXME */ -static GstBuffer * -gst_sdlvideosink_buffer_new (GstBufferPool * pool, - gint64 location, guint size, gpointer user_data) -{ - GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (user_data); - GstBuffer *buffer; - - if (!sdlvideosink->overlay) - return NULL; - - if (!gst_sdlvideosink_lock (sdlvideosink)) { - return NULL; - } - - /* this protects the buffer from being written over multiple times */ - g_mutex_lock (sdlvideosink->lock); - - buffer = gst_buffer_new (); - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_DONTFREE); - GST_BUFFER_DATA (buffer) = sdlvideosink->overlay->pixels[0]; - if (sdlvideosink->format == SDL_YV12_OVERLAY || - sdlvideosink->format == SDL_IYUV_OVERLAY) { - GST_BUFFER_SIZE (buffer) = - sdlvideosink->width * sdlvideosink->height * 3 / 2; - } else { - GST_BUFFER_SIZE (buffer) = sdlvideosink->width * sdlvideosink->height * 2; - } - GST_BUFFER_MAXSIZE (buffer) = GST_BUFFER_SIZE (buffer); - - return buffer; -} - -static void -gst_sdlvideosink_buffer_free (GstBufferPool * pool, - GstBuffer * buffer, gpointer user_data) -{ - GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (user_data); - - g_mutex_unlock (sdlvideosink->lock); - gst_sdlvideosink_unlock (sdlvideosink); - - gst_buffer_default_free (buffer); -} - - -static GstBufferPool * -gst_sdlvideosink_get_bufferpool (GstPad * pad) -{ - GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (gst_pad_get_parent (pad)); - - if (sdlvideosink->overlay) - return sdlvideosink->bufferpool; - - return NULL; -} -#endif - -static void -gst_sdlvideosink_init (GstSDLVideoSink * sdlvideosink, - GstSDLVideoSinkClass * g_class) -{ - - sdlvideosink->width = -1; - sdlvideosink->height = -1; - sdlvideosink->framerate_n = 0; - sdlvideosink->framerate_d = 1; - sdlvideosink->full_screen = FALSE; - - sdlvideosink->overlay = NULL; - sdlvideosink->screen = NULL; - - sdlvideosink->xwindow_id = 0; - - //sdlvideosink->capslist = capslist; - - sdlvideosink->init = FALSE; - - sdlvideosink->event_thread = NULL; - sdlvideosink->running = FALSE; - - sdlvideosink->lock = g_mutex_new (); -} - -static void -gst_sdlvideosink_interface_init (GstImplementsInterfaceClass * klass) -{ - klass->supported = gst_sdlvideosink_supported; -} - -static gboolean -gst_sdlvideosink_supported (GstImplementsInterface * interface, - GType iface_type) -{ - GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (interface); - gboolean result = FALSE; - - /* check SDL for whether it was compiled against X, FB, etc. */ - if (iface_type == GST_TYPE_X_OVERLAY) { - gchar tmp[4]; - - if (!sdlvideosink->init) { - g_mutex_lock (sdlvideosink->lock); - SDL_Init (SDL_INIT_VIDEO); - - /* True if the video driver is X11 */ - result = (strcmp ("x11", SDL_VideoDriverName (tmp, 4)) == 0); - SDL_QuitSubSystem (SDL_INIT_VIDEO); - g_mutex_unlock (sdlvideosink->lock); - } else - result = sdlvideosink->is_xwindows; - } else if (iface_type == GST_TYPE_NAVIGATION) - result = TRUE; - - return result; -} - -/* SDL Video sink and X overlay: - * - * SDL supports creating an Xv window/overlay within an existing X window - * through the horrible mechanism of setting the WINDOWID environment - * variable. - * It will then display the x overlay within that window, but not at the - * full window size. Instead, we need to explicitly tell SDL the size. - * - * Unfortunately, the XOverlay interface in GStreamer doesn't supply - * that information. The only way to get it would be to do what X[v]imagesink - * does and retrieve it using X11 calls, and linking to Xlib. That would - * defeat the whole purpose of using the SDL abstraction and plugin entirely - * however. - * - * I have no nice solution to this problem for you, dear readers. - */ -static void -gst_sdlvideosink_xoverlay_init (GstXOverlayClass * klass) -{ - klass->set_window_handle = gst_sdlvideosink_xoverlay_set_window_handle; -} - -static void -gst_sdlvideosink_xoverlay_set_window_handle (GstXOverlay * overlay, - guintptr handle) -{ - GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (overlay); - unsigned long parent = (unsigned long) handle; - - if (sdlvideosink->xwindow_id == parent) - return; - - sdlvideosink->xwindow_id = parent; - - /* are we running yet? */ - if (sdlvideosink->init) { - gboolean negotiated; - - g_mutex_lock (sdlvideosink->lock); - - negotiated = (sdlvideosink->overlay != NULL); - - if (negotiated) - gst_sdlvideosink_destroy (sdlvideosink); - - /* Call initsdl to set the WINDOWID env var urk */ - gst_sdlvideosink_initsdl (sdlvideosink); - - if (negotiated) - gst_sdlvideosink_create (sdlvideosink); - - g_mutex_unlock (sdlvideosink->lock); - } -} - -static guint32 -gst_sdlvideosink_get_sdl_from_fourcc (GstSDLVideoSink * sdlvideosink, - guint32 code) -{ - switch (code) { - /* Note: SDL_IYUV_OVERLAY does not always work for I420 */ - case GST_MAKE_FOURCC ('I', '4', '2', '0'): - return SDL_YV12_OVERLAY; - case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): - return SDL_YV12_OVERLAY; - case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): - return SDL_YUY2_OVERLAY; - case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): - return SDL_UYVY_OVERLAY; - case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): - return SDL_YVYU_OVERLAY; - default: - return 0; - } -} - -static gboolean -gst_sdlvideosink_lock (GstSDLVideoSink * sdlvideosink) -{ - /* assure that we've got a screen */ - if (!sdlvideosink->screen || !sdlvideosink->overlay) - goto no_setup; - - /* Lock SDL/yuv-overlay */ - if (SDL_MUSTLOCK (sdlvideosink->screen)) { - if (SDL_LockSurface (sdlvideosink->screen) < 0) - goto could_not_lock; - } - if (SDL_LockYUVOverlay (sdlvideosink->overlay) < 0) - goto lock_yuv; - - return TRUE; - - /* ERRORS */ -no_setup: - { - GST_ELEMENT_ERROR (sdlvideosink, LIBRARY, TOO_LAZY, (NULL), - ("Tried to lock screen without being set-up")); - return FALSE; - } -could_not_lock: - { - GST_ELEMENT_ERROR (sdlvideosink, LIBRARY, TOO_LAZY, (NULL), - ("SDL: couldn't lock the SDL video window: %s", SDL_GetError ())); - return FALSE; - } -lock_yuv: - { - GST_ELEMENT_ERROR (sdlvideosink, LIBRARY, TOO_LAZY, (NULL), - ("SDL: couldn\'t lock the SDL YUV overlay: %s", SDL_GetError ())); - return FALSE; - } -} - - -static void -gst_sdlvideosink_unlock (GstSDLVideoSink * sdlvideosink) -{ - /* Unlock SDL_overlay */ - SDL_UnlockYUVOverlay (sdlvideosink->overlay); - if (SDL_MUSTLOCK (sdlvideosink->screen)) - SDL_UnlockSurface (sdlvideosink->screen); -} - -/* Must be called with ->lock held */ -static void -gst_sdlvideosink_deinitsdl (GstSDLVideoSink * sdlvideosink) -{ - if (sdlvideosink->init) { - sdlvideosink->running = FALSE; - if (sdlvideosink->event_thread) { - g_mutex_unlock (sdlvideosink->lock); - g_thread_join (sdlvideosink->event_thread); - g_mutex_lock (sdlvideosink->lock); - sdlvideosink->event_thread = NULL; - } - - SDL_QuitSubSystem (SDL_INIT_VIDEO); - sdlvideosink->init = FALSE; - - } -} - -/* Process pending events. Call with ->lock held */ -static void -gst_sdlv_process_events (GstSDLVideoSink * sdlvideosink) -{ - SDL_Event event; - int numevents; - char *keysym = NULL; - - do { - SDL_PumpEvents (); - numevents = SDL_PeepEvents (&event, 1, SDL_GETEVENT, - SDL_KEYDOWNMASK | SDL_KEYUPMASK | - SDL_MOUSEMOTIONMASK | SDL_MOUSEBUTTONDOWNMASK | - SDL_MOUSEBUTTONUPMASK | SDL_QUITMASK | SDL_VIDEORESIZEMASK); - - if (numevents > 0 && (event.type == SDL_KEYUP || event.type == SDL_KEYDOWN)) { - keysym = SDL_GetKeyName (event.key.keysym.sym); - } - - if (numevents > 0) { - g_mutex_unlock (sdlvideosink->lock); - switch (event.type) { - case SDL_MOUSEMOTION: - gst_navigation_send_mouse_event (GST_NAVIGATION (sdlvideosink), - "mouse-move", 0, event.motion.x, event.motion.y); - break; - case SDL_MOUSEBUTTONDOWN: - gst_navigation_send_mouse_event (GST_NAVIGATION (sdlvideosink), - "mouse-button-press", - event.button.button, event.button.x, event.button.y); - break; - case SDL_MOUSEBUTTONUP: - gst_navigation_send_mouse_event (GST_NAVIGATION (sdlvideosink), - "mouse-button-release", - event.button.button, event.button.x, event.button.y); - break; - case SDL_KEYUP: - GST_DEBUG ("key press event %s !", - SDL_GetKeyName (event.key.keysym.sym)); - gst_navigation_send_key_event (GST_NAVIGATION (sdlvideosink), - "key-release", keysym); - break; - case SDL_KEYDOWN: - if (SDLK_ESCAPE != event.key.keysym.sym) { - GST_DEBUG ("key press event %s !", - SDL_GetKeyName (event.key.keysym.sym)); - gst_navigation_send_key_event (GST_NAVIGATION (sdlvideosink), - "key-press", keysym); - break; - } else { - /* fall through */ - } - case SDL_QUIT: - sdlvideosink->running = FALSE; - GST_ELEMENT_ERROR (sdlvideosink, RESOURCE, OPEN_WRITE, - ("Video output device is gone."), - ("We were running fullscreen and user " - "pressed the ESC key, stopping playback.")); - break; - case SDL_VIDEORESIZE: - /* create a SDL window of the size requested by the user */ - g_mutex_lock (sdlvideosink->lock); - GST_VIDEO_SINK_WIDTH (sdlvideosink) = event.resize.w; - GST_VIDEO_SINK_HEIGHT (sdlvideosink) = event.resize.h; - gst_sdlvideosink_create (sdlvideosink); - g_mutex_unlock (sdlvideosink->lock); - break; - } - g_mutex_lock (sdlvideosink->lock); - } - } while (numevents > 0); -} - -static gpointer -gst_sdlvideosink_event_thread (GstSDLVideoSink * sdlvideosink) -{ - g_mutex_lock (sdlvideosink->lock); - while (sdlvideosink->running) { - gst_sdlv_process_events (sdlvideosink); - - /* Done events, sleep for 50 ms */ - g_mutex_unlock (sdlvideosink->lock); - g_usleep (50000); - g_mutex_lock (sdlvideosink->lock); - } - g_mutex_unlock (sdlvideosink->lock); - - return NULL; -} - -/* Must be called with the SDL lock held */ -static gboolean -gst_sdlvideosink_initsdl (GstSDLVideoSink * sdlvideosink) -{ - gst_sdlvideosink_deinitsdl (sdlvideosink); - - if (sdlvideosink->is_xwindows && !sdlvideosink->xwindow_id) { - g_mutex_unlock (sdlvideosink->lock); - gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (sdlvideosink)); - g_mutex_lock (sdlvideosink->lock); - } - - if (!sdlvideosink->xwindow_id) { - g_unsetenv ("SDL_WINDOWID"); - } else { - char SDL_hack[32]; - - sprintf (SDL_hack, "%lu", sdlvideosink->xwindow_id); - g_setenv ("SDL_WINDOWID", SDL_hack, 1); - } - - /* Initialize the SDL library */ - if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) - goto init_failed; - - sdlvideosink->init = TRUE; - - sdlvideosink->running = TRUE; - sdlvideosink->event_thread = - g_thread_create ((GThreadFunc) gst_sdlvideosink_event_thread, - sdlvideosink, TRUE, NULL); - - return TRUE; - - /* ERRORS */ -init_failed: - { - GST_ELEMENT_ERROR (sdlvideosink, LIBRARY, INIT, (NULL), - ("Couldn't initialize SDL: %s", SDL_GetError ())); - return FALSE; - } -} - -/* Must be called with the sdl lock held */ -static void -gst_sdlvideosink_destroy (GstSDLVideoSink * sdlvideosink) -{ - if (sdlvideosink->overlay) { - SDL_FreeYUVOverlay (sdlvideosink->overlay); - sdlvideosink->overlay = NULL; - } - - if (sdlvideosink->screen) { - SDL_FreeSurface (sdlvideosink->screen); - sdlvideosink->screen = NULL; - } - sdlvideosink->xwindow_id = 0; -} - -/* Must be called with the sdl lock held */ -static gboolean -gst_sdlvideosink_create (GstSDLVideoSink * sdlvideosink) -{ - if (GST_VIDEO_SINK_HEIGHT (sdlvideosink) <= 0) - GST_VIDEO_SINK_HEIGHT (sdlvideosink) = sdlvideosink->height; - if (GST_VIDEO_SINK_WIDTH (sdlvideosink) <= 0) - GST_VIDEO_SINK_WIDTH (sdlvideosink) = sdlvideosink->width; - - gst_sdlvideosink_destroy (sdlvideosink); - - if (sdlvideosink->is_xwindows && !sdlvideosink->xwindow_id) { - g_mutex_unlock (sdlvideosink->lock); - gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (sdlvideosink)); - g_mutex_lock (sdlvideosink->lock); - } - - /* create a SDL window of the size requested by the user */ - if (sdlvideosink->full_screen) { - sdlvideosink->screen = - SDL_SetVideoMode (GST_VIDEO_SINK_WIDTH (sdlvideosink), - GST_VIDEO_SINK_HEIGHT (sdlvideosink), 0, - SDL_SWSURFACE | SDL_FULLSCREEN); - } else { - sdlvideosink->screen = - SDL_SetVideoMode (GST_VIDEO_SINK_WIDTH (sdlvideosink), - GST_VIDEO_SINK_HEIGHT (sdlvideosink), 0, SDL_HWSURFACE | SDL_RESIZABLE); - } - if (sdlvideosink->screen == NULL) - goto no_screen; - - /* create a new YUV overlay */ - sdlvideosink->overlay = SDL_CreateYUVOverlay (sdlvideosink->width, - sdlvideosink->height, sdlvideosink->format, sdlvideosink->screen); - if (sdlvideosink->overlay == NULL) - goto no_overlay; - - - GST_DEBUG ("Using a %dx%d %dbpp SDL screen with a %dx%d \'%" - GST_FOURCC_FORMAT "\' YUV overlay", GST_VIDEO_SINK_WIDTH (sdlvideosink), - GST_VIDEO_SINK_HEIGHT (sdlvideosink), - sdlvideosink->screen->format->BitsPerPixel, sdlvideosink->width, - sdlvideosink->height, GST_FOURCC_ARGS (sdlvideosink->format)); - - sdlvideosink->rect.x = 0; - sdlvideosink->rect.y = 0; - sdlvideosink->rect.w = GST_VIDEO_SINK_WIDTH (sdlvideosink); - sdlvideosink->rect.h = GST_VIDEO_SINK_HEIGHT (sdlvideosink); - - /*SDL_DisplayYUVOverlay (sdlvideosink->overlay, &(sdlvideosink->rect)); */ - - GST_DEBUG ("sdlvideosink: setting %08x (%" GST_FOURCC_FORMAT ")", - sdlvideosink->format, GST_FOURCC_ARGS (sdlvideosink->format)); - - return TRUE; - - /* ERRORS */ -no_screen: - { - GST_ELEMENT_ERROR (sdlvideosink, LIBRARY, TOO_LAZY, (NULL), - ("SDL: Couldn't set %dx%d: %s", GST_VIDEO_SINK_WIDTH (sdlvideosink), - GST_VIDEO_SINK_HEIGHT (sdlvideosink), SDL_GetError ())); - return FALSE; - } -no_overlay: - { - GST_ELEMENT_ERROR (sdlvideosink, LIBRARY, TOO_LAZY, (NULL), - ("SDL: Couldn't create SDL YUV overlay (%dx%d \'%" GST_FOURCC_FORMAT - "\'): %s", sdlvideosink->width, sdlvideosink->height, - GST_FOURCC_ARGS (sdlvideosink->format), SDL_GetError ())); - return FALSE; - } -} - -static gboolean -gst_sdlvideosink_setcaps (GstBaseSink * bsink, GstCaps * vscapslist) -{ - GstSDLVideoSink *sdlvideosink; - GstStructure *structure; - gboolean res = TRUE; - - sdlvideosink = GST_SDLVIDEOSINK (bsink); - - structure = gst_caps_get_structure (vscapslist, 0); - gst_structure_get_fourcc (structure, "format", &sdlvideosink->fourcc); - sdlvideosink->format = - gst_sdlvideosink_get_sdl_from_fourcc (sdlvideosink, sdlvideosink->fourcc); - gst_structure_get_int (structure, "width", &sdlvideosink->width); - gst_structure_get_int (structure, "height", &sdlvideosink->height); - gst_structure_get_fraction (structure, "framerate", - &sdlvideosink->framerate_n, &sdlvideosink->framerate_d); - - g_mutex_lock (sdlvideosink->lock); - if (!sdlvideosink->format || !gst_sdlvideosink_create (sdlvideosink)) - res = FALSE; - g_mutex_unlock (sdlvideosink->lock); - - return res; -} - - -static GstFlowReturn -gst_sdlvideosink_show_frame (GstBaseSink * bsink, GstBuffer * buf) -{ - - GstSDLVideoSink *sdlvideosink; - - sdlvideosink = GST_SDLVIDEOSINK (bsink); - - g_mutex_lock (sdlvideosink->lock); - if (!sdlvideosink->init || - !sdlvideosink->overlay || !sdlvideosink->overlay->pixels) - goto not_init; - - /* if (GST_BUFFER_DATA (buf) != sdlvideosink->overlay->pixels[0]) */ - if (TRUE) { - guint8 *out; - gint l; - - if (!gst_sdlvideosink_lock (sdlvideosink)) - goto cannot_lock; - - /* buf->yuv - FIXME: bufferpool! */ - if (sdlvideosink->format == SDL_YV12_OVERLAY) { - guint8 *y, *u, *v; - - switch (sdlvideosink->fourcc) { - case GST_MAKE_FOURCC ('I', '4', '2', '0'): - y = GST_BUFFER_DATA (buf); - /* I420 is YV12 with switched colour planes and different offsets */ - v = y + I420_U_OFFSET (sdlvideosink->width, sdlvideosink->height); - u = y + I420_V_OFFSET (sdlvideosink->width, sdlvideosink->height); - break; - case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): - y = GST_BUFFER_DATA (buf); - u = y + I420_U_OFFSET (sdlvideosink->width, sdlvideosink->height); - v = y + I420_V_OFFSET (sdlvideosink->width, sdlvideosink->height); - break; - default: - gst_sdlvideosink_unlock (sdlvideosink); - g_mutex_unlock (sdlvideosink->lock); - g_return_val_if_reached (GST_FLOW_ERROR); - } - - /* Y Plane */ - out = sdlvideosink->overlay->pixels[0]; - for (l = 0; l < sdlvideosink->height; l++) { - memcpy (out, y, I420_Y_ROWSTRIDE (sdlvideosink->width)); - out += sdlvideosink->overlay->pitches[0]; - y += I420_Y_ROWSTRIDE (sdlvideosink->width); - } - - /* U plane */ - out = sdlvideosink->overlay->pixels[1]; - for (l = 0; l < (sdlvideosink->height / 2); l++) { - memcpy (out, u, I420_U_ROWSTRIDE (sdlvideosink->width)); - out += sdlvideosink->overlay->pitches[1]; - u += I420_U_ROWSTRIDE (sdlvideosink->width); - } - - /* V plane */ - out = sdlvideosink->overlay->pixels[2]; - for (l = 0; l < (sdlvideosink->height / 2); l++) { - memcpy (out, v, I420_V_ROWSTRIDE (sdlvideosink->width)); - out += sdlvideosink->overlay->pitches[2]; - v += I420_V_ROWSTRIDE (sdlvideosink->width); - } - } else { - guint8 *in = GST_BUFFER_DATA (buf); - gint in_stride = sdlvideosink->width * 2; - - out = sdlvideosink->overlay->pixels[0]; - - for (l = 0; l < sdlvideosink->height; l++) { - memcpy (out, in, in_stride); - out += sdlvideosink->overlay->pitches[0]; - in += in_stride; - } - } - gst_sdlvideosink_unlock (sdlvideosink); - } - - /* Show, baby, show! */ - SDL_DisplayYUVOverlay (sdlvideosink->overlay, &(sdlvideosink->rect)); - - /* Handle any resize */ - gst_sdlv_process_events (sdlvideosink); - - g_mutex_unlock (sdlvideosink->lock); - - return GST_FLOW_OK; - - /* ERRORS */ -not_init: - { - GST_ELEMENT_ERROR (sdlvideosink, CORE, NEGOTIATION, (NULL), - ("not negotiated.")); - g_mutex_unlock (sdlvideosink->lock); - return GST_FLOW_NOT_NEGOTIATED; - } -cannot_lock: - { - /* lock function posted detailed message */ - g_mutex_unlock (sdlvideosink->lock); - return GST_FLOW_ERROR; - } -} - - -static void -gst_sdlvideosink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstSDLVideoSink *sdlvideosink; - - sdlvideosink = GST_SDLVIDEOSINK (object); - - switch (prop_id) { - case PROP_FULLSCREEN: - sdlvideosink->full_screen = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -gst_sdlvideosink_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstSDLVideoSink *sdlvideosink; - - sdlvideosink = GST_SDLVIDEOSINK (object); - - switch (prop_id) { - case PROP_FULLSCREEN: - g_value_set_boolean (value, sdlvideosink->full_screen); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static GstStateChangeReturn -gst_sdlvideosink_change_state (GstElement * element, GstStateChange transition) -{ - GstSDLVideoSink *sdlvideosink; - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - g_return_val_if_fail (GST_IS_SDLVIDEOSINK (element), - GST_STATE_CHANGE_FAILURE); - sdlvideosink = GST_SDLVIDEOSINK (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - sdlvideosink->is_xwindows = GST_IS_X_OVERLAY (sdlvideosink); - g_mutex_lock (sdlvideosink->lock); - if (!gst_sdlvideosink_initsdl (sdlvideosink)) { - g_mutex_unlock (sdlvideosink->lock); - goto init_failed; - } - GST_OBJECT_FLAG_SET (sdlvideosink, GST_SDLVIDEOSINK_OPEN); - g_mutex_unlock (sdlvideosink->lock); - break; - default: /* do nothing */ - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - sdlvideosink->framerate_n = 0; - sdlvideosink->framerate_d = 1; - g_mutex_lock (sdlvideosink->lock); - gst_sdlvideosink_destroy (sdlvideosink); - g_mutex_unlock (sdlvideosink->lock); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - g_mutex_lock (sdlvideosink->lock); - gst_sdlvideosink_deinitsdl (sdlvideosink); - GST_OBJECT_FLAG_UNSET (sdlvideosink, GST_SDLVIDEOSINK_OPEN); - g_mutex_unlock (sdlvideosink->lock); - break; - default: /* do nothing */ - break; - } - return ret; - -init_failed: - { - /* method posted detailed error message */ - GST_DEBUG_OBJECT (sdlvideosink, "init failed"); - return GST_STATE_CHANGE_FAILURE; - } -} - - -static void -gst_sdlvideosink_navigation_send_event (GstNavigation * navigation, - GstStructure * structure) -{ - GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (navigation); - GstEvent *event; - GstVideoRectangle dst = { 0, }; - GstVideoRectangle src = { 0, }; - GstVideoRectangle result; - double x, y, old_x, old_y; - GstPad *pad = NULL; - - src.w = GST_VIDEO_SINK_WIDTH (sdlvideosink); - src.h = GST_VIDEO_SINK_HEIGHT (sdlvideosink); - dst.w = sdlvideosink->width; - dst.h = sdlvideosink->height; - gst_video_sink_center_rect (src, dst, &result, FALSE); - - event = gst_event_new_navigation (structure); - - /* Our coordinates can be wrong here if we centered the video */ - - /* Converting pointer coordinates to the non scaled geometry */ - if (gst_structure_get_double (structure, "pointer_x", &old_x)) { - x = old_x; - - if (x >= result.x && x <= (result.x + result.w)) { - x -= result.x; - x *= sdlvideosink->width; - x /= result.w; - } else { - x = 0; - } - GST_DEBUG_OBJECT (sdlvideosink, "translated navigation event x " - "coordinate from %f to %f", old_x, x); - gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, x, NULL); - } - if (gst_structure_get_double (structure, "pointer_y", &old_y)) { - y = old_y; - - if (y >= result.y && y <= (result.y + result.h)) { - y -= result.y; - y *= sdlvideosink->height; - y /= result.h; - } else { - y = 0; - } - GST_DEBUG_OBJECT (sdlvideosink, "translated navigation event y " - "coordinate from %f to %f", old_y, y); - gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, y, NULL); - } - - pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (sdlvideosink)); - - if (GST_IS_PAD (pad) && GST_IS_EVENT (event)) { - gst_pad_send_event (pad, event); - - gst_object_unref (pad); - } -} - -static void -gst_sdlvideosink_navigation_init (GstNavigationInterface * iface) -{ - iface->send_event = gst_sdlvideosink_navigation_send_event; -} diff --git a/ext/sdl/sdlvideosink.h b/ext/sdl/sdlvideosink.h deleted file mode 100644 index eff752f38..000000000 --- a/ext/sdl/sdlvideosink.h +++ /dev/null @@ -1,82 +0,0 @@ -/* GStreamer SDL plugin - * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * 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_SDLVIDEOSINK_H__ -#define __GST_SDLVIDEOSINK_H__ - -#include <gst/video/gstvideosink.h> - -#include <SDL.h> - -G_BEGIN_DECLS - -#define GST_TYPE_SDLVIDEOSINK \ - (gst_sdlvideosink_get_type()) -#define GST_SDLVIDEOSINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SDLVIDEOSINK,GstSDLVideoSink)) -#define GST_SDLVIDEOSINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SDLVIDEOSINK,GstSDLVideoSinkClass)) -#define GST_IS_SDLVIDEOSINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SDLVIDEOSINK)) -#define GST_IS_SDLVIDEOSINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SDLVIDEOSINK)) - -typedef enum { - GST_SDLVIDEOSINK_OPEN = (GST_ELEMENT_FLAG_LAST << 0), - - GST_SDLVIDEOSINK_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 2), -} GstSDLVideoSinkFlags; - -typedef struct _GstSDLVideoSink GstSDLVideoSink; -typedef struct _GstSDLVideoSinkClass GstSDLVideoSinkClass; - -struct _GstSDLVideoSink { - GstVideoSink videosink; - - guint32 format; /* the SDL format */ - guint32 fourcc; /* our fourcc from the caps */ - - gint width, height; /* the size of the incoming YUV stream */ - unsigned long xwindow_id; - gboolean is_xwindows; - - gint framerate_n; - gint framerate_d; - - gboolean full_screen; - gboolean init; - gboolean running; - GThread *event_thread; - SDL_Surface *screen; - SDL_Overlay *overlay; - SDL_Rect rect; - - GMutex *lock; -}; - -struct _GstSDLVideoSinkClass { - GstVideoSinkClass parent_class; - -}; - -GType gst_sdlvideosink_get_type(void); - -G_END_DECLS - -#endif /* __GST_SDLVIDEOSINK_H__ */ diff --git a/ext/sndio/Makefile.am b/ext/sndio/Makefile.am deleted file mode 100644 index 03a42b1a5..000000000 --- a/ext/sndio/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -plugin_LTLIBRARIES = libgstsndio.la - -libgstsndio_la_SOURCES = gstsndio.c sndiosink.c sndiosrc.c -libgstsndio_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) -libgstsndio_la_LIBADD = \ - $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) \ - $(SNDIO_LIBS) -libgstsndio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) - -noinst_HEADERS = sndiosink.h sndiosrc.h -EXTRA_DIST = diff --git a/ext/sndio/gstsndio.c b/ext/sndio/gstsndio.c deleted file mode 100644 index af8252ec0..000000000 --- a/ext/sndio/gstsndio.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) <2008> Jacob Meuser <jakemsr@sdf.lonestar.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "sndiosink.h" -#include "sndiosrc.h" - -#include "gst/gst-i18n-plugin.h" - -GST_DEBUG_CATEGORY (gst_sndio_debug); - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_element_register (plugin, "sndiosrc", GST_RANK_PRIMARY, - GST_TYPE_SNDIOSRC) || - !gst_element_register (plugin, "sndiosink", GST_RANK_PRIMARY, - GST_TYPE_SNDIOSINK)) { - return FALSE; - } - - GST_DEBUG_CATEGORY_INIT (gst_sndio_debug, "sndio", 0, "sndio elements"); - -#ifdef ENABLE_NLS - GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, - LOCALEDIR); - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); -#endif /* ENABLE_NLS */ - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "sndio", - "sndio support for GStreamer", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/sndio/sndiosink.c b/ext/sndio/sndiosink.c deleted file mode 100644 index c9d0f719a..000000000 --- a/ext/sndio/sndiosink.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright (C) <2008> Jacob Meuser <jakemsr@sdf.lonestar.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/** - * SECTION:element-sndiosink - * @see_also: #GstAutoAudioSink - * - * <refsect2> - * <para> - * This element outputs sound to a sound card using sndio. - * </para> - * <para> - * Simple example pipeline that plays an Ogg/Vorbis file via sndio: - * <programlisting> - * gst-launch-1.0 -v filesrc location=foo.ogg ! decodebin ! audioconvert ! audioresample ! sndiosink - * </programlisting> - * </para> - * </refsect2> - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "sndiosink.h" -#include <unistd.h> -#include <errno.h> - -#include <gst/gst-i18n-plugin.h> - -GST_DEBUG_CATEGORY_EXTERN (gst_sndio_debug); -#define GST_CAT_DEFAULT gst_sndio_debug - -enum -{ - PROP_0, - PROP_HOST -}; - -static GstStaticPadTemplate sndio_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "endianness = (int) { 1234, 4321 }, " - "signed = (boolean) { TRUE, FALSE }, " - "width = (int) { 8, 16, 24, 32 }, " - "depth = (int) { 8, 16, 24, 32 }, " - "rate = (int) [ 8000, 192000 ], " "channels = (int) [ 1, 16 ] ") - ); - -static void gst_sndiosink_finalize (GObject * object); - -static GstCaps *gst_sndiosink_getcaps (GstBaseSink * bsink); - -static gboolean gst_sndiosink_open (GstAudioSink * asink); -static gboolean gst_sndiosink_close (GstAudioSink * asink); -static gboolean gst_sndiosink_prepare (GstAudioSink * asink, - GstRingBufferSpec * spec); -static gboolean gst_sndiosink_unprepare (GstAudioSink * asink); -static guint gst_sndiosink_write (GstAudioSink * asink, gpointer data, - guint length); -static guint gst_sndiosink_delay (GstAudioSink * asink); -static void gst_sndiosink_reset (GstAudioSink * asink); - -static void gst_sndiosink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_sndiosink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_sndiosink_cb (void *addr, int delta); - -GST_BOILERPLATE (GstSndioSink, gst_sndiosink, GstAudioSink, - GST_TYPE_AUDIO_SINK); - -static void -gst_sndiosink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_static_metadata (element_class, - "Sndio audio sink", - "Sink/Audio", - "Plays audio through sndio", "Jacob Meuser <jakemsr@sdf.lonestar.org>"); - - gst_element_class_add_static_pad_template (element_class, - &sndio_sink_factory); -} - -static void -gst_sndiosink_class_init (GstSndioSinkClass * klass) -{ - GObjectClass *gobject_class; - GstBaseSinkClass *gstbasesink_class; - GstBaseAudioSinkClass *gstbaseaudiosink_class; - GstAudioSinkClass *gstaudiosink_class; - - gobject_class = (GObjectClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass; - gstaudiosink_class = (GstAudioSinkClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_sndiosink_finalize; - - gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_sndiosink_getcaps); - - gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_sndiosink_open); - gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_sndiosink_close); - gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_sndiosink_prepare); - gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_sndiosink_unprepare); - gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_sndiosink_write); - gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_sndiosink_delay); - gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_sndiosink_reset); - - gobject_class->set_property = gst_sndiosink_set_property; - gobject_class->get_property = gst_sndiosink_get_property; - - /* default value is filled in the _init method */ - g_object_class_install_property (gobject_class, PROP_HOST, - g_param_spec_string ("host", "Host", - "Device or socket sndio will access", NULL, G_PARAM_READWRITE)); -} - -static void -gst_sndiosink_init (GstSndioSink * sndiosink, GstSndioSinkClass * klass) -{ - sndiosink->hdl = NULL; - sndiosink->host = g_strdup (g_getenv ("AUDIODEVICE")); -} - -static void -gst_sndiosink_finalize (GObject * object) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK (object); - - gst_caps_replace (&sndiosink->cur_caps, NULL); - g_free (sndiosink->host); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static GstCaps * -gst_sndiosink_getcaps (GstBaseSink * bsink) -{ - GstSndioSink *sndiosink; - - sndiosink = GST_SNDIOSINK (bsink); - - /* no hdl, we're done with the template caps */ - if (sndiosink->cur_caps == NULL) { - GST_LOG_OBJECT (sndiosink, "getcaps called, returning template caps"); - return NULL; - } - - GST_LOG_OBJECT (sndiosink, "returning %" GST_PTR_FORMAT, sndiosink->cur_caps); - - return gst_caps_ref (sndiosink->cur_caps); -} - -static gboolean -gst_sndiosink_open (GstAudioSink * asink) -{ - GstPadTemplate *pad_template; - GstSndioSink *sndiosink; - struct sio_par par; - struct sio_cap cap; - GArray *rates, *chans; - GValue rates_v = { 0 }; - GValue chans_v = { 0 }; - GValue value = { 0 }; - struct sio_enc enc; - struct sio_conf conf; - int confs[SIO_NCONF]; - int rate, chan; - int i, j, k; - int nconfs; - - sndiosink = GST_SNDIOSINK (asink); - - GST_DEBUG_OBJECT (sndiosink, "open"); - - /* conect */ - sndiosink->hdl = sio_open (sndiosink->host, SIO_PLAY, 0); - - if (sndiosink->hdl == NULL) - goto couldnt_connect; - - /* Use sndio defaults as the only encodings, but get the supported - * sample rates and number of channels. - */ - - if (!sio_getpar (sndiosink->hdl, &par)) - goto no_server_info; - - if (!sio_getcap (sndiosink->hdl, &cap)) - goto no_server_info; - - rates = g_array_new (FALSE, FALSE, sizeof (int)); - chans = g_array_new (FALSE, FALSE, sizeof (int)); - - /* find confs that have the default encoding */ - nconfs = 0; - for (i = 0; i < cap.nconf; i++) { - for (j = 0; j < SIO_NENC; j++) { - if (cap.confs[i].enc & (1 << j)) { - enc = cap.enc[j]; - if (enc.bits == par.bits && enc.sig == par.sig && enc.le == par.le) { - confs[nconfs] = i; - nconfs++; - break; - } - } - } - } - - /* find the rates and channels of the confs that have the default encoding */ - for (i = 0; i < nconfs; i++) { - conf = cap.confs[confs[i]]; - /* rates */ - for (j = 0; j < SIO_NRATE; j++) { - if (conf.rate & (1 << j)) { - rate = cap.rate[j]; - for (k = 0; k < rates->len && rate; k++) { - if (rate == g_array_index (rates, int, k)) - rate = 0; - } - /* add in ascending order */ - if (rate) { - for (k = 0; k < rates->len; k++) { - if (rate < g_array_index (rates, int, k)) - { - g_array_insert_val (rates, k, rate); - break; - } - } - if (k == rates->len) - g_array_append_val (rates, rate); - } - } - } - /* channels */ - for (j = 0; j < SIO_NCHAN; j++) { - if (conf.pchan & (1 << j)) { - chan = cap.pchan[j]; - for (k = 0; k < chans->len && chan; k++) { - if (chan == g_array_index (chans, int, k)) - chan = 0; - } - /* add in ascending order */ - if (chan) { - for (k = 0; k < chans->len; k++) { - if (chan < g_array_index (chans, int, k)) - { - g_array_insert_val (chans, k, chan); - break; - } - } - if (k == chans->len) - g_array_append_val (chans, chan); - } - } - } - } - /* not sure how this can happen, but it might */ - if (cap.nconf == 0) { - g_array_append_val (rates, par.rate); - g_array_append_val (chans, par.pchan); - } - - g_value_init (&rates_v, GST_TYPE_LIST); - g_value_init (&chans_v, GST_TYPE_LIST); - g_value_init (&value, G_TYPE_INT); - - for (i = 0; i < rates->len; i++) { - g_value_set_int (&value, g_array_index (rates, int, i)); - gst_value_list_append_value (&rates_v, &value); - } - for (i = 0; i < chans->len; i++) { - g_value_set_int (&value, g_array_index (chans, int, i)); - gst_value_list_append_value (&chans_v, &value); - } - - g_array_free (rates, TRUE); - g_array_free (chans, TRUE); - - pad_template = gst_static_pad_template_get (&sndio_sink_factory); - sndiosink->cur_caps = - gst_caps_copy (gst_pad_template_get_caps (pad_template)); - gst_object_unref (pad_template); - - for (i = 0; i < sndiosink->cur_caps->structs->len; i++) { - GstStructure *s; - - s = gst_caps_get_structure (sndiosink->cur_caps, i); - gst_structure_set (s, "endianness", G_TYPE_INT, par.le ? 1234 : 4321, NULL); - gst_structure_set (s, "signed", G_TYPE_BOOLEAN, par.sig ? TRUE : FALSE, - NULL); - gst_structure_set (s, "width", G_TYPE_INT, par.bits, NULL); - // gst_structure_set (s, "depth", G_TYPE_INT, par.bps * 8, NULL); /* XXX */ - gst_structure_set_value (s, "rate", &rates_v); - gst_structure_set_value (s, "channels", &chans_v); - } - - return TRUE; - - /* ERRORS */ -couldnt_connect: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, OPEN_WRITE, - (_("Could not establish connection to sndio")), - ("can't open connection to sndio")); - return FALSE; - } -no_server_info: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, OPEN_WRITE, - (_("Failed to query sndio capabilities")), - ("couldn't get sndio info!")); - return FALSE; - } -} - -static gboolean -gst_sndiosink_close (GstAudioSink * asink) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - - GST_DEBUG_OBJECT (sndiosink, "close"); - - gst_caps_replace (&sndiosink->cur_caps, NULL); - sio_close (sndiosink->hdl); - sndiosink->hdl = NULL; - - return TRUE; -} - -static void -gst_sndiosink_cb (void *addr, int delta) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK ((GstAudioSink *) addr); - - sndiosink->realpos += delta; - - if (sndiosink->realpos >= sndiosink->playpos) - sndiosink->latency = 0; - else - sndiosink->latency = sndiosink->playpos - sndiosink->realpos; -} - -static gboolean -gst_sndiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - struct sio_par par; - int spec_bpf; - - GST_DEBUG_OBJECT (sndiosink, "prepare"); - - sndiosink->playpos = sndiosink->realpos = sndiosink->latency = 0; - - sio_initpar (&par); - par.sig = spec->sign; - par.le = !spec->bigend; - par.bits = spec->width; - // par.bps = spec->depth / 8; /* XXX */ - par.rate = spec->rate; - par.pchan = spec->channels; - - spec_bpf = ((spec->width / 8) * spec->channels); - - par.appbufsz = (spec->segsize * spec->segtotal) / spec_bpf; - - if (!sio_setpar (sndiosink->hdl, &par)) - goto cannot_configure; - - sio_getpar (sndiosink->hdl, &par); - - spec->sign = par.sig; - spec->bigend = !par.le; - spec->width = par.bits; - // spec->depth = par.bps * 8; /* XXX */ - spec->rate = par.rate; - spec->channels = par.pchan; - - sndiosink->bpf = par.bps * par.pchan; - - spec->segsize = par.round * par.pchan * par.bps; - spec->segtotal = par.bufsz / par.round; - - /* FIXME: this is wrong for signed ints (and the - * audioringbuffers should do it for us anyway) */ - spec->silence_sample[0] = 0; - spec->silence_sample[1] = 0; - spec->silence_sample[2] = 0; - spec->silence_sample[3] = 0; - - sio_onmove (sndiosink->hdl, gst_sndiosink_cb, sndiosink); - - if (!sio_start (sndiosink->hdl)) - goto cannot_start; - - GST_INFO_OBJECT (sndiosink, "successfully opened connection to sndio"); - - return TRUE; - - /* ERRORS */ -cannot_configure: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, OPEN_WRITE, - (_("Could not configure sndio")), ("can't configure sndio")); - return FALSE; - } -cannot_start: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, OPEN_WRITE, - (_("Could not start sndio")), ("can't start sndio")); - return FALSE; - } -} - -static gboolean -gst_sndiosink_unprepare (GstAudioSink * asink) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - - if (sndiosink->hdl == NULL) - return TRUE; - - sio_stop (sndiosink->hdl); - - return TRUE; -} - -static guint -gst_sndiosink_write (GstAudioSink * asink, gpointer data, guint length) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - guint done; - - done = sio_write (sndiosink->hdl, data, length); - - if (done == 0) - goto write_error; - - sndiosink->playpos += (done / sndiosink->bpf); - - data = (char *) data + done; - - return done; - - /* ERRORS */ -write_error: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, WRITE, - ("Failed to write data to sndio"), GST_ERROR_SYSTEM); - return 0; - } -} - -static guint -gst_sndiosink_delay (GstAudioSink * asink) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - - if (sndiosink->latency == (guint) - 1) { - GST_WARNING_OBJECT (asink, "couldn't get latency"); - return 0; - } - - GST_DEBUG_OBJECT (asink, "got latency: %u", sndiosink->latency); - - return sndiosink->latency; -} - -static void -gst_sndiosink_reset (GstAudioSink * asink) -{ - /* no way to flush the buffers with sndio ? */ - - GST_DEBUG_OBJECT (asink, "reset called"); -} - -static void -gst_sndiosink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK (object); - - switch (prop_id) { - case PROP_HOST: - g_free (sndiosink->host); - sndiosink->host = g_value_dup_string (value); - break; - default: - break; - } -} - -static void -gst_sndiosink_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK (object); - - switch (prop_id) { - case PROP_HOST: - g_value_set_string (value, sndiosink->host); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/ext/sndio/sndiosink.h b/ext/sndio/sndiosink.h deleted file mode 100644 index 25bb8799b..000000000 --- a/ext/sndio/sndiosink.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) <2008> Jacob Meuser <jakemsr@sdf.lonestar.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - - -#ifndef __GST_SNDIOSINK_H__ -#define __GST_SNDIOSINK_H__ - -#include <sndio.h> - -#include <gst/gst.h> -#include <gst/audio/gstaudiosink.h> - -G_BEGIN_DECLS - -#define GST_TYPE_SNDIOSINK \ - (gst_sndiosink_get_type()) -#define GST_SNDIOSINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SNDIOSINK,GstSndioSink)) -#define GST_SNDIOSINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SNDIOSINK,GstSndioSinkClass)) -#define GST_IS_SNDIOSINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SNDIOSINK)) -#define GST_IS_SNDIOSINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SNDIOSINK)) - -typedef struct _GstSndioSink GstSndioSink; -typedef struct _GstSndioSinkClass GstSndioSinkClass; - -struct _GstSndioSink { - GstAudioSink sink; - - struct sio_hdl *hdl; - gchar *host; - - /* bytes per frame */ - int bpf; - - /* frames counts */ - volatile long long realpos; - volatile long long playpos; - volatile guint latency; - - GstCaps *cur_caps; -}; - -struct _GstSndioSinkClass { - GstAudioSinkClass parent_class; -}; - -GType gst_sndiosink_get_type (void); - -G_END_DECLS - -#endif /* __GST_SNDIOSINK_H__ */ diff --git a/ext/sndio/sndiosrc.c b/ext/sndio/sndiosrc.c deleted file mode 100644 index 5721f42d1..000000000 --- a/ext/sndio/sndiosrc.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (C) <2008> Jacob Meuser <jakemsr@sdf.lonestar.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/** - * SECTION:element-sndiosrc - * @see_also: #GstAutoAudioSrc - * - * <refsect2> - * <para> - * This element retrieves samples from a sound card using sndio. - * </para> - * <para> - * Simple example pipeline that records an Ogg/Vorbis file via sndio: - * <programlisting> - * gst-launch-1.0 -v sndiosrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=foo.ogg - * </programlisting> - * </para> - * </refsect2> - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "sndiosrc.h" -#include <unistd.h> -#include <errno.h> - -#include <gst/gst-i18n-plugin.h> - -GST_DEBUG_CATEGORY_EXTERN (gst_sndio_debug); -#define GST_CAT_DEFAULT gst_sndio_debug - -enum -{ - PROP_0, - PROP_HOST -}; - -static GstStaticPadTemplate sndio_src_factory = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "endianness = (int) { 1234, 4321 }, " - "signed = (boolean) { TRUE, FALSE }, " - "width = (int) { 8, 16, 24, 32 }, " - "depth = (int) { 8, 16, 24, 32 }, " - "rate = (int) [ 8000, 192000 ], " "channels = (int) [ 1, 16 ] ") - ); - -static void gst_sndiosrc_finalize (GObject * object); - -static GstCaps *gst_sndiosrc_getcaps (GstBaseSrc * bsrc); - -static gboolean gst_sndiosrc_open (GstAudioSrc * asrc); -static gboolean gst_sndiosrc_close (GstAudioSrc * asrc); -static gboolean gst_sndiosrc_prepare (GstAudioSrc * asrc, - GstRingBufferSpec * spec); -static gboolean gst_sndiosrc_unprepare (GstAudioSrc * asrc); -static guint gst_sndiosrc_read (GstAudioSrc * asrc, gpointer data, - guint length); -static guint gst_sndiosrc_delay (GstAudioSrc * asrc); -static void gst_sndiosrc_reset (GstAudioSrc * asrc); - -static void gst_sndiosrc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_sndiosrc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_sndiosrc_cb (void *addr, int delta); - -GST_BOILERPLATE (GstSndioSrc, gst_sndiosrc, GstAudioSrc, GST_TYPE_AUDIO_SRC); - -static void -gst_sndiosrc_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_static_metadata (element_class, - "Sndio audio source", - "Source/Audio", - "Records audio through sndio", "Jacob Meuser <jakemsr@sdf.lonestar.org>"); - - gst_element_class_add_static_pad_template (element_class, &sndio_src_factory); -} - -static void -gst_sndiosrc_class_init (GstSndioSrcClass * klass) -{ - GObjectClass *gobject_class; - GstBaseSrcClass *gstbasesrc_class; - GstBaseAudioSrcClass *gstbaseaudiosrc_class; - GstAudioSrcClass *gstaudiosrc_class; - - gobject_class = (GObjectClass *) klass; - gstbasesrc_class = (GstBaseSrcClass *) klass; - gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass; - gstaudiosrc_class = (GstAudioSrcClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_sndiosrc_finalize; - - gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_sndiosrc_getcaps); - - gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_sndiosrc_open); - gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_sndiosrc_close); - gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_sndiosrc_prepare); - gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_sndiosrc_unprepare); - gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_sndiosrc_read); - gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_sndiosrc_delay); - gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_sndiosrc_reset); - - gobject_class->set_property = gst_sndiosrc_set_property; - gobject_class->get_property = gst_sndiosrc_get_property; - - /* default value is filled in the _init method */ - g_object_class_install_property (gobject_class, PROP_HOST, - g_param_spec_string ("host", "Host", - "Device or socket sndio will access", NULL, G_PARAM_READWRITE)); -} - -static void -gst_sndiosrc_init (GstSndioSrc * sndiosrc, GstSndioSrcClass * klass) -{ - sndiosrc->hdl = NULL; - sndiosrc->host = g_strdup (g_getenv ("AUDIODEVICE")); -} - -static void -gst_sndiosrc_finalize (GObject * object) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC (object); - - gst_caps_replace (&sndiosrc->cur_caps, NULL); - g_free (sndiosrc->host); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static GstCaps * -gst_sndiosrc_getcaps (GstBaseSrc * bsrc) -{ - GstSndioSrc *sndiosrc; - - sndiosrc = GST_SNDIOSRC (bsrc); - - /* no hdl, we're done with the template caps */ - if (sndiosrc->cur_caps == NULL) { - GST_LOG_OBJECT (sndiosrc, "getcaps called, returning template caps"); - return NULL; - } - - GST_LOG_OBJECT (sndiosrc, "returning %" GST_PTR_FORMAT, sndiosrc->cur_caps); - - return gst_caps_ref (sndiosrc->cur_caps); -} - -static gboolean -gst_sndiosrc_open (GstAudioSrc * asrc) -{ - GstPadTemplate *pad_template; - GstSndioSrc *sndiosrc; - struct sio_par par; - struct sio_cap cap; - GArray *rates, *chans; - GValue rates_v = { 0 }; - GValue chans_v = { 0 }; - GValue value = { 0 }; - struct sio_enc enc; - struct sio_conf conf; - int confs[SIO_NCONF]; - int rate, chan; - int i, j, k; - int nconfs; - - sndiosrc = GST_SNDIOSRC (asrc); - - GST_DEBUG_OBJECT (sndiosrc, "open"); - - /* connect */ - sndiosrc->hdl = sio_open (sndiosrc->host, SIO_REC, 0); - - if (sndiosrc->hdl == NULL) - goto couldnt_connect; - - /* Use sndio defaults as the only encodings, but get the supported - * sample rates and number of channels. - */ - - if (!sio_getpar (sndiosrc->hdl, &par)) - goto no_server_info; - - if (!sio_getcap (sndiosrc->hdl, &cap)) - goto no_server_info; - - rates = g_array_new (FALSE, FALSE, sizeof (int)); - chans = g_array_new (FALSE, FALSE, sizeof (int)); - - /* find confs that have the default encoding */ - nconfs = 0; - for (i = 0; i < cap.nconf; i++) { - for (j = 0; j < SIO_NENC; j++) { - if (cap.confs[i].enc & (1 << j)) { - enc = cap.enc[j]; - if (enc.bits == par.bits && enc.sig == par.sig && enc.le == par.le) { - confs[nconfs] = i; - nconfs++; - break; - } - } - } - } - - /* find the rates and channels of the confs that have the default encoding */ - for (i = 0; i < nconfs; i++) { - conf = cap.confs[confs[i]]; - /* rates */ - for (j = 0; j < SIO_NRATE; j++) { - if (conf.rate & (1 << j)) { - rate = cap.rate[j]; - for (k = 0; k < rates->len && rate; k++) { - if (rate == g_array_index (rates, int, k)) - rate = 0; - } - /* add in ascending order */ - if (rate) { - for (k = 0; k < rates->len; k++) { - if (rate < g_array_index (rates, int, k)) - { - g_array_insert_val (rates, k, rate); - break; - } - } - if (k == rates->len) - g_array_append_val (rates, rate); - } - } - } - /* channels */ - for (j = 0; j < SIO_NCHAN; j++) { - if (conf.rchan & (1 << j)) { - chan = cap.rchan[j]; - for (k = 0; k < chans->len && chan; k++) { - if (chan == g_array_index (chans, int, k)) - chan = 0; - } - /* add in ascending order */ - if (chan) { - for (k = 0; k < chans->len; k++) { - if (chan < g_array_index (chans, int, k)) - { - g_array_insert_val (chans, k, chan); - break; - } - } - if (k == chans->len) - g_array_append_val (chans, chan); - } - } - } - } - /* not sure how this can happen, but it might */ - if (cap.nconf == 0) { - g_array_append_val (rates, par.rate); - g_array_append_val (chans, par.rchan); - } - - g_value_init (&rates_v, GST_TYPE_LIST); - g_value_init (&chans_v, GST_TYPE_LIST); - g_value_init (&value, G_TYPE_INT); - - for (i = 0; i < rates->len; i++) { - g_value_set_int (&value, g_array_index (rates, int, i)); - gst_value_list_append_value (&rates_v, &value); - } - for (i = 0; i < chans->len; i++) { - g_value_set_int (&value, g_array_index (chans, int, i)); - gst_value_list_append_value (&chans_v, &value); - } - - g_array_free (rates, TRUE); - g_array_free (chans, TRUE); - - pad_template = gst_static_pad_template_get (&sndio_src_factory); - sndiosrc->cur_caps = gst_caps_copy (gst_pad_template_get_caps (pad_template)); - gst_object_unref (pad_template); - - for (i = 0; i < sndiosrc->cur_caps->structs->len; i++) { - GstStructure *s; - - s = gst_caps_get_structure (sndiosrc->cur_caps, i); - gst_structure_set (s, "endianness", G_TYPE_INT, par.le ? 1234 : 4321, NULL); - gst_structure_set (s, "signed", G_TYPE_BOOLEAN, par.sig ? TRUE : FALSE, - NULL); - gst_structure_set (s, "width", G_TYPE_INT, par.bits, NULL); - // gst_structure_set (s, "depth", G_TYPE_INT, par.bps * 8, NULL); /* XXX */ - gst_structure_set_value (s, "rate", &rates_v); - gst_structure_set_value (s, "channels", &chans_v); - } - - return TRUE; - - /* ERRORS */ -couldnt_connect: - { - GST_ELEMENT_ERROR (sndiosrc, RESOURCE, OPEN_READ, - (_("Could not establish connection to sndio")), - ("can't open connection to sndio")); - return FALSE; - } -no_server_info: - { - GST_ELEMENT_ERROR (sndiosrc, RESOURCE, OPEN_READ, - (_("Failed to query sndio capabilities")), - ("couldn't get sndio info!")); - return FALSE; - } -} - -static gboolean -gst_sndiosrc_close (GstAudioSrc * asrc) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC (asrc); - - GST_DEBUG_OBJECT (sndiosrc, "close"); - - gst_caps_replace (&sndiosrc->cur_caps, NULL); - sio_close (sndiosrc->hdl); - sndiosrc->hdl = NULL; - - return TRUE; -} - -static void -gst_sndiosrc_cb (void *addr, int delta) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC ((GstAudioSrc *) addr); - - sndiosrc->realpos += delta; - - if (sndiosrc->readpos >= sndiosrc->realpos) - sndiosrc->latency = 0; - else - sndiosrc->latency = sndiosrc->realpos - sndiosrc->readpos; -} - -static gboolean -gst_sndiosrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC (asrc); - struct sio_par par; - int spec_bpf; - - GST_DEBUG_OBJECT (sndiosrc, "prepare"); - - sndiosrc->readpos = sndiosrc->realpos = sndiosrc->latency = 0; - - sio_initpar (&par); - par.sig = spec->sign; - par.le = !spec->bigend; - par.bits = spec->width; - // par.bps = spec->depth / 8; /* XXX */ - par.rate = spec->rate; - par.rchan = spec->channels; - - spec_bpf = ((spec->width / 8) * spec->channels); - - par.round = spec->segsize / spec_bpf; - par.appbufsz = (spec->segsize * spec->segtotal) / spec_bpf; - - if (!sio_setpar (sndiosrc->hdl, &par)) - goto cannot_configure; - - sio_getpar (sndiosrc->hdl, &par); - - spec->sign = par.sig; - spec->bigend = !par.le; - spec->width = par.bits; - // spec->depth = par.bps * 8; /* XXX */ - spec->rate = par.rate; - spec->channels = par.rchan; - - sndiosrc->bpf = par.bps * par.rchan; - - spec->segsize = par.round * par.rchan * par.bps; - spec->segtotal = par.bufsz / par.round; - - /* FIXME: this is wrong for signed ints (and the - * audioringbuffers should do it for us anyway) */ - spec->silence_sample[0] = 0; - spec->silence_sample[1] = 0; - spec->silence_sample[2] = 0; - spec->silence_sample[3] = 0; - - sio_onmove (sndiosrc->hdl, gst_sndiosrc_cb, sndiosrc); - - if (!sio_start (sndiosrc->hdl)) - goto cannot_start; - - GST_INFO_OBJECT (sndiosrc, "successfully opened connection to sndio"); - - return TRUE; - - /* ERRORS */ -cannot_configure: - { - GST_ELEMENT_ERROR (sndiosrc, RESOURCE, OPEN_READ, - (_("Could not configure sndio")), ("can't configure sndio")); - return FALSE; - } -cannot_start: - { - GST_ELEMENT_ERROR (sndiosrc, RESOURCE, OPEN_READ, - (_("Could not start sndio")), ("can't start sndio")); - return FALSE; - } -} - -static gboolean -gst_sndiosrc_unprepare (GstAudioSrc * asrc) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC (asrc); - - if (sndiosrc->hdl == NULL) - return TRUE; - - sio_stop (sndiosrc->hdl); - - return TRUE; -} - -static guint -gst_sndiosrc_read (GstAudioSrc * asrc, gpointer data, guint length) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC (asrc); - guint done; - - done = sio_read (sndiosrc->hdl, data, length); - - if (done == 0) - goto read_error; - - sndiosrc->readpos += (done / sndiosrc->bpf); - - data = (char *) data + done; - - return done; - - /* ERRORS */ -read_error: - { - GST_ELEMENT_ERROR (sndiosrc, RESOURCE, READ, - ("Failed to read data from sndio"), GST_ERROR_SYSTEM); - return 0; - } -} - -static guint -gst_sndiosrc_delay (GstAudioSrc * asrc) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC (asrc); - - if (sndiosrc->latency == (guint) - 1) { - GST_WARNING_OBJECT (asrc, "couldn't get latency"); - return 0; - } - - GST_DEBUG_OBJECT (asrc, "got latency: %u", sndiosrc->latency); - - return sndiosrc->latency; -} - -static void -gst_sndiosrc_reset (GstAudioSrc * asrc) -{ - /* no way to flush the buffers with sndio ? */ - - GST_DEBUG_OBJECT (asrc, "reset called"); -} - -static void -gst_sndiosrc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC (object); - - switch (prop_id) { - case PROP_HOST: - g_free (sndiosrc->host); - sndiosrc->host = g_value_dup_string (value); - break; - default: - break; - } -} - -static void -gst_sndiosrc_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstSndioSrc *sndiosrc = GST_SNDIOSRC (object); - - switch (prop_id) { - case PROP_HOST: - g_value_set_string (value, sndiosrc->host); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/ext/sndio/sndiosrc.h b/ext/sndio/sndiosrc.h deleted file mode 100644 index 48e7a2606..000000000 --- a/ext/sndio/sndiosrc.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) <2008> Jacob Meuser <jakemsr@sdf.lonestar.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - - -#ifndef __GST_SNDIOSRC_H__ -#define __GST_SNDIOSRC_H__ - -#include <sndio.h> - -#include <gst/gst.h> -#include <gst/audio/gstaudiosrc.h> - -G_BEGIN_DECLS - -#define GST_TYPE_SNDIOSRC \ - (gst_sndiosrc_get_type()) -#define GST_SNDIOSRC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SNDIOSRC,GstSndioSrc)) -#define GST_SNDIOSRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SNDIOSRC,GstSndioSrcClass)) -#define GST_IS_SNDIOSRC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SNDIOSRC)) -#define GST_IS_SNDIOSRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SNDIOSRC)) - -typedef struct _GstSndioSrc GstSndioSrc; -typedef struct _GstSndioSrcClass GstSndioSrcClass; - -struct _GstSndioSrc { - GstAudioSrc src; - - struct sio_hdl *hdl; - gchar *host; - - /* bytes per frame */ - int bpf; - - /* frames counts */ - volatile long long realpos; - volatile long long readpos; - volatile guint latency; - - GstCaps *cur_caps; -}; - -struct _GstSndioSrcClass { - GstAudioSrcClass parent_class; -}; - -GType gst_sndiosrc_get_type (void); - -G_END_DECLS - -#endif /* __GST_SNDIOSRC_H__ */ diff --git a/ext/timidity/gsttimidity.c b/ext/timidity/gsttimidity.c deleted file mode 100644 index 0b3f3769a..000000000 --- a/ext/timidity/gsttimidity.c +++ /dev/null @@ -1,821 +0,0 @@ -/* - * gsttimdity - timidity plugin for gstreamer - * - * Copyright 2007 Wouter Paesen <wouter@blue-gate.be> - * - * 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-timidity - * @see_also: wildmidi - * - * This element renders midi-files as audio streams using - * <ulink url="http://timidity.sourceforge.net/">Timidity</ulink>. - * - * <refsect2> - * <title>Example pipeline</title> - * |[ - * gst-launch filesrc location=song.mid ! timidity ! alsasink - * ]| This example pipeline will parse the midi and render to raw audio which is - * played via alsa. - * </refsect2> - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <gst/gst.h> -#include <string.h> - -#include "gsttimidity.h" - -#ifndef TIMIDITY_CFG -#define TIMIDITY_CFG "/etc/timidity.cfg" -#endif - -GST_DEBUG_CATEGORY_STATIC (gst_timidity_debug); -#define GST_CAT_DEFAULT gst_timidity_debug - -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - /* FILL ME */ -}; - -static gboolean gst_timidity_src_event (GstPad * pad, GstEvent * event); -static GstStateChangeReturn gst_timidity_change_state (GstElement * element, - GstStateChange transition); -static gboolean gst_timidity_activate (GstPad * pad); -static gboolean gst_timidity_activatepull (GstPad * pad, gboolean active); -static void gst_timidity_loop (GstPad * sinkpad); -static gboolean gst_timidity_src_query (GstPad * pad, GstQuery * query); -static gboolean gst_timidity_set_song_options (GstTimidity * timidity, - MidSongOptions * options); - -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/midi; audio/riff-midi") - ); - -static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "rate = (int) 44100, " - "channels = (int) 2, " - "endianness = (int) LITTLE_ENDIAN, " - "width = (int) 16, " "depth = (int) 16, " "signed = (boolean) true")); - -GST_BOILERPLATE (GstTimidity, gst_timidity, GstElement, GST_TYPE_ELEMENT); - -static void -gst_timidity_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_add_static_pad_template (element_class, &src_factory); - gst_element_class_add_static_pad_template (element_class, &sink_factory); - gst_element_class_set_static_metadata (element_class, "Timidity", - "Codec/Decoder/Audio", - "Midi Synthesizer Element", "Wouter Paesen <wouter@blue-gate.be>"); -} - -/* initialize the plugin's class */ -static void -gst_timidity_class_init (GstTimidityClass * klass) -{ - GstElementClass *gstelement_class; - - gstelement_class = (GstElementClass *) klass; - gstelement_class->change_state = gst_timidity_change_state; -} - -/* initialize the new element - * instantiate pads and add them to element - * set functions - * initialize structure - */ -static void -gst_timidity_init (GstTimidity * filter, GstTimidityClass * g_class) -{ - GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter); - - /* initialise timidity library */ - if (mid_init ((char *) TIMIDITY_CFG) == 0) { - filter->initialized = TRUE; - } else { - GST_WARNING ("can't initialize timidity with config: " TIMIDITY_CFG); - } - - filter->sinkpad = - gst_pad_new_from_template (gst_element_class_get_pad_template (klass, - "sink"), "sink"); - - gst_pad_set_activatepull_function (filter->sinkpad, - gst_timidity_activatepull); - gst_pad_set_activate_function (filter->sinkpad, gst_timidity_activate); - gst_pad_set_setcaps_function (filter->sinkpad, gst_pad_set_caps); - gst_pad_use_fixed_caps (filter->sinkpad); - gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); - - filter->srcpad = - gst_pad_new_from_template (gst_element_class_get_pad_template (klass, - "src"), "src"); - - gst_pad_set_query_function (filter->srcpad, gst_timidity_src_query); - gst_pad_set_event_function (filter->srcpad, gst_timidity_src_event); - gst_pad_use_fixed_caps (filter->srcpad); - gst_pad_set_setcaps_function (filter->srcpad, gst_pad_set_caps); - - gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); - - filter->song_options->buffer_size = 2048; - filter->song_options->rate = 44100; - filter->song_options->format = MID_AUDIO_S16LSB; - filter->song_options->channels = 2; - - gst_timidity_set_song_options (filter, filter->song_options); - - gst_segment_init (filter->o_segment, GST_FORMAT_DEFAULT); -} - -static gboolean -gst_timidity_set_song_options (GstTimidity * timidity, MidSongOptions * options) -{ - gint64 bps; - - switch (options->format) { - case MID_AUDIO_U8: - case MID_AUDIO_S8: - bps = 1; - break; - case MID_AUDIO_U16LSB: - case MID_AUDIO_S16LSB: - case MID_AUDIO_U16MSB: - case MID_AUDIO_S16MSB: - bps = 2; - break; - default: - return FALSE; - } - - bps *= options->channels; - - if (options != timidity->song_options) - memcpy (timidity->song_options, options, sizeof (MidSongOptions)); - - timidity->bytes_per_frame = bps; - timidity->time_per_frame = GST_SECOND / (GstClockTime) options->rate; - - return TRUE; -} - -static gboolean -gst_timidity_src_convert (GstTimidity * timidity, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - gint64 frames; - - if (src_format == *dest_format) { - *dest_value = src_value; - goto done; - } - - switch (src_format) { - case GST_FORMAT_TIME: - frames = src_value / timidity->time_per_frame; - break; - case GST_FORMAT_BYTES: - frames = src_value / (timidity->bytes_per_frame); - break; - case GST_FORMAT_DEFAULT: - frames = src_value; - break; - default: - res = FALSE; - goto done; - } - - switch (*dest_format) { - case GST_FORMAT_TIME: - *dest_value = frames * timidity->time_per_frame; - break; - case GST_FORMAT_BYTES: - *dest_value = frames * timidity->bytes_per_frame; - break; - case GST_FORMAT_DEFAULT: - *dest_value = frames; - break; - default: - res = FALSE; - break; - } - -done: - return res; -} - -static gboolean -gst_timidity_src_query (GstPad * pad, GstQuery * query) -{ - gboolean res = TRUE; - GstTimidity *timidity = GST_TIMIDITY (gst_pad_get_parent (pad)); - GstFormat src_format, dst_format; - gint64 src_value, dst_value; - - if (!timidity->song) { - gst_object_unref (timidity); - return FALSE; - } - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_DURATION: - gst_query_set_duration (query, GST_FORMAT_TIME, - GST_MSECOND * (gint64) mid_song_get_total_time (timidity->song)); - break; - case GST_QUERY_POSITION: - gst_query_set_position (query, GST_FORMAT_TIME, - timidity->o_segment->last_stop * timidity->time_per_frame); - break; - case GST_QUERY_CONVERT: - gst_query_parse_convert (query, &src_format, &src_value, - &dst_format, NULL); - - res = - gst_timidity_src_convert (timidity, src_format, src_value, - &dst_format, &dst_value); - if (res) - gst_query_set_convert (query, src_format, src_value, dst_format, - dst_value); - - break; - case GST_QUERY_FORMATS: - gst_query_set_formats (query, 3, - GST_FORMAT_TIME, GST_FORMAT_BYTES, GST_FORMAT_DEFAULT); - break; - case GST_QUERY_SEGMENT:{ - GstFormat format; - gint64 start, stop; - - format = timidity->o_segment->format; - - start = - gst_segment_to_stream_time (timidity->o_segment, format, - timidity->o_segment->start); - if ((stop = timidity->o_segment->stop) == -1) - stop = timidity->o_segment->duration; - else - stop = gst_segment_to_stream_time (timidity->o_segment, format, stop); - - gst_query_set_segment (query, timidity->o_segment->rate, format, start, - stop); - res = TRUE; - break; - } - case GST_QUERY_SEEKING: - gst_query_set_seeking (query, timidity->o_segment->format, - TRUE, 0, timidity->o_len); - break; - default: - res = FALSE; - break; - } - - gst_object_unref (timidity); - return res; -} - -static gboolean -gst_timidity_get_upstream_size (GstTimidity * timidity, gint64 * size) -{ - GstFormat format = GST_FORMAT_BYTES; - gboolean res = FALSE; - GstPad *peer = gst_pad_get_peer (timidity->sinkpad); - - if (peer != NULL) - res = gst_pad_query_duration (peer, &format, size) && *size >= 0; - - gst_object_unref (peer); - return res; -} - -static GstSegment * -gst_timidity_get_segment (GstTimidity * timidity, GstFormat format, - gboolean update) -{ - gint64 start = 0, stop = 0, time = 0; - - GstSegment *segment = gst_segment_new (); - - gst_timidity_src_convert (timidity, - timidity->o_segment->format, timidity->o_segment->start, &format, &start); - - if (timidity->o_segment->stop == GST_CLOCK_TIME_NONE) { - stop = GST_CLOCK_TIME_NONE; - } else { - gst_timidity_src_convert (timidity, - timidity->o_segment->format, timidity->o_segment->stop, &format, &stop); - } - - gst_timidity_src_convert (timidity, - timidity->o_segment->format, timidity->o_segment->time, &format, &time); - - gst_segment_set_newsegment_full (segment, update, - timidity->o_segment->rate, timidity->o_segment->applied_rate, - format, start, stop, time); - - segment->last_stop = time; - - return segment; -} - -static GstEvent * -gst_timidity_get_new_segment_event (GstTimidity * timidity, GstFormat format, - gboolean update) -{ - GstSegment *segment; - GstEvent *event; - - segment = gst_timidity_get_segment (timidity, format, update); - - event = gst_event_new_new_segment_full (update, - segment->rate, segment->applied_rate, segment->format, - segment->start, segment->stop, segment->time); - - gst_segment_free (segment); - - return event; -} - -static gboolean -gst_timidity_src_event (GstPad * pad, GstEvent * event) -{ - gboolean res = FALSE; - GstTimidity *timidity = GST_TIMIDITY (gst_pad_get_parent (pad)); - - GST_DEBUG_OBJECT (pad, "%s event received", GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - { - gdouble rate; - GstFormat src_format, dst_format; - GstSeekFlags flags; - GstSeekType start_type, stop_type; - gint64 orig_start, start = 0, stop = 0; - gboolean flush, update; - - if (!timidity->song) - break; - - gst_event_parse_seek (event, &rate, &src_format, &flags, - &start_type, &orig_start, &stop_type, &stop); - - dst_format = GST_FORMAT_DEFAULT; - - gst_timidity_src_convert (timidity, src_format, orig_start, - &dst_format, &start); - gst_timidity_src_convert (timidity, src_format, stop, &dst_format, &stop); - - flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH); - - if (flush) { - GST_DEBUG ("performing flush"); - gst_pad_push_event (timidity->srcpad, gst_event_new_flush_start ()); - } else { - gst_pad_stop_task (timidity->sinkpad); - } - - GST_PAD_STREAM_LOCK (timidity->sinkpad); - - if (flush) { - gst_pad_push_event (timidity->srcpad, gst_event_new_flush_stop ()); - } - - gst_segment_set_seek (timidity->o_segment, rate, dst_format, flags, - start_type, start, stop_type, stop, &update); - - if (flags & GST_SEEK_FLAG_SEGMENT) { - GST_DEBUG_OBJECT (timidity, "received segment seek %d, %d", - (gint) start_type, (gint) stop_type); - } else { - GST_DEBUG_OBJECT (timidity, "received normal seek %d", - (gint) start_type); - update = FALSE; - } - - gst_pad_push_event (timidity->srcpad, - gst_timidity_get_new_segment_event (timidity, GST_FORMAT_TIME, - update)); - - timidity->o_seek = TRUE; - - gst_pad_start_task (timidity->sinkpad, - (GstTaskFunction) gst_timidity_loop, timidity->sinkpad, NULL); - - GST_PAD_STREAM_UNLOCK (timidity->sinkpad); - GST_DEBUG ("seek done"); - } - res = TRUE; - break; - default: - break; - } - - g_object_unref (timidity); - return res; -} - -static gboolean -gst_timidity_activate (GstPad * sinkpad) -{ - if (gst_pad_check_pull_range (sinkpad)) - return gst_pad_activate_pull (sinkpad, TRUE); - - return FALSE; -} - -static gboolean -gst_timidity_activatepull (GstPad * pad, gboolean active) -{ - if (active) { - return gst_pad_start_task (pad, (GstTaskFunction) gst_timidity_loop, pad, - NULL); - } else { - return gst_pad_stop_task (pad); - } -} - -static GstBuffer * -gst_timidity_allocate_buffer (GstTimidity * timidity, gint64 samples) -{ - return gst_buffer_new_and_alloc (samples * timidity->bytes_per_frame); -} - -static GstBuffer * -gst_timidity_clip_buffer (GstTimidity * timidity, GstBuffer * buffer) -{ - gint64 new_start, new_stop; - gint64 offset, length; - GstBuffer *out; - - return buffer; - - if (!gst_segment_clip (timidity->o_segment, GST_FORMAT_DEFAULT, - GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer), - &new_start, &new_stop)) { - gst_buffer_unref (buffer); - return NULL; - } - - if (GST_BUFFER_OFFSET (buffer) == new_start && - GST_BUFFER_OFFSET_END (buffer) == new_stop) - return buffer; - - offset = new_start - GST_BUFFER_OFFSET (buffer); - length = new_stop - new_start; - - out = gst_buffer_create_sub (buffer, offset * timidity->bytes_per_frame, - length * timidity->bytes_per_frame); - - GST_BUFFER_OFFSET (out) = new_start; - GST_BUFFER_OFFSET_END (out) = new_stop; - GST_BUFFER_TIMESTAMP (out) = new_start * timidity->time_per_frame; - GST_BUFFER_DURATION (out) = (new_stop - new_start) * timidity->time_per_frame; - - gst_buffer_unref (buffer); - - return out; -} - -/* generate audio data and advance internal timers */ -static GstBuffer * -gst_timidity_fill_buffer (GstTimidity * timidity, GstBuffer * buffer) -{ - size_t bytes_read; - gint64 samples; - - bytes_read = mid_song_read_wave (timidity->song, GST_BUFFER_DATA (buffer), - GST_BUFFER_SIZE (buffer)); - - if (bytes_read == 0) { - gst_buffer_unref (buffer); - return NULL; - } - - GST_BUFFER_OFFSET (buffer) = - timidity->o_segment->last_stop * timidity->bytes_per_frame; - GST_BUFFER_TIMESTAMP (buffer) = - timidity->o_segment->last_stop * timidity->time_per_frame; - - if (bytes_read < GST_BUFFER_SIZE (buffer)) { - GstBuffer *old = buffer; - - buffer = gst_buffer_create_sub (buffer, 0, bytes_read); - gst_buffer_unref (old); - } - - samples = GST_BUFFER_SIZE (buffer) / timidity->bytes_per_frame; - - timidity->o_segment->last_stop += samples; - - GST_BUFFER_OFFSET_END (buffer) = - timidity->o_segment->last_stop * timidity->bytes_per_frame; - GST_BUFFER_DURATION (buffer) = samples * timidity->time_per_frame; - - GST_DEBUG_OBJECT (timidity, - "generated buffer %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT - " (%" G_GINT64_FORMAT " samples)", - GST_TIME_ARGS ((guint64) GST_BUFFER_TIMESTAMP (buffer)), - GST_TIME_ARGS (((guint64) (GST_BUFFER_TIMESTAMP (buffer) + - GST_BUFFER_DURATION (buffer)))), samples); - - return buffer; -} - -static GstBuffer * -gst_timidity_get_buffer (GstTimidity * timidity) -{ - GstBuffer *out; - - out = - gst_timidity_fill_buffer (timidity, - gst_timidity_allocate_buffer (timidity, 256)); - - if (!out) - return NULL; - - return gst_timidity_clip_buffer (timidity, out); -} - -static void -gst_timidity_loop (GstPad * sinkpad) -{ - GstTimidity *timidity = GST_TIMIDITY (GST_PAD_PARENT (sinkpad)); - GstBuffer *out; - GstFlowReturn ret; - - if (timidity->mididata_size == 0) { - if (!gst_timidity_get_upstream_size (timidity, &timidity->mididata_size)) { - GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), - ("Unable to get song length")); - goto paused; - } - - g_free (timidity->mididata); - - timidity->mididata = g_malloc (timidity->mididata_size); - timidity->mididata_offset = 0; - return; - } - - if (timidity->mididata_offset < timidity->mididata_size) { - GstBuffer *buffer = NULL; - gint64 size; - - GST_DEBUG_OBJECT (timidity, "loading song"); - - ret = - gst_pad_pull_range (timidity->sinkpad, timidity->mididata_offset, - -1, &buffer); - if (ret != GST_FLOW_OK) { - GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), - ("Unable to load song")); - goto paused; - } - - size = timidity->mididata_size - timidity->mididata_offset; - if (GST_BUFFER_SIZE (buffer) < size) - size = GST_BUFFER_SIZE (buffer); - - memmove (timidity->mididata + timidity->mididata_offset, - GST_BUFFER_DATA (buffer), size); - gst_buffer_unref (buffer); - - timidity->mididata_offset += size; - GST_DEBUG_OBJECT (timidity, "Song loaded"); - return; - } - - if (!timidity->song) { - MidIStream *stream; - GstTagList *tags = NULL; - gchar *text; - - GST_DEBUG_OBJECT (timidity, "Parsing song"); - -#if defined(LIBTIMIDITY_VERSION) && LIBTIMIDITY_VERSION < 0x000200L - stream = - mid_istream_open_mem (timidity->mididata, timidity->mididata_size, 0); -#else - stream = mid_istream_open_mem (timidity->mididata, timidity->mididata_size); -#endif - - timidity->song = mid_song_load (stream, timidity->song_options); - mid_istream_close (stream); - - if (!timidity->song) { - GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), - ("Unable to parse midi")); - goto paused; - } - - mid_song_start (timidity->song); - timidity->o_len = (GST_MSECOND * - (GstClockTime) mid_song_get_total_time (timidity->song)) / - timidity->time_per_frame; - gst_segment_set_newsegment (timidity->o_segment, FALSE, 1.0, - GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0); - - - gst_pad_push_event (timidity->srcpad, - gst_timidity_get_new_segment_event (timidity, GST_FORMAT_TIME, FALSE)); - - /* extract tags */ - text = mid_song_get_meta (timidity->song, MID_SONG_TEXT); - if (text) { - tags = gst_tag_list_new (); - gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text, NULL); - - //g_free (text); - } - - text = mid_song_get_meta (timidity->song, MID_SONG_COPYRIGHT); - if (text) { - if (tags == NULL) - tags = gst_tag_list_new (); - gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, - GST_TAG_COPYRIGHT, text, NULL); - - //g_free (text); - } - - if (tags) { - gst_element_found_tags (GST_ELEMENT (timidity), tags); - } - - GST_DEBUG_OBJECT (timidity, "Parsing song done"); - return; - } - - if (timidity->o_segment_changed) { - GstSegment *segment = gst_timidity_get_segment (timidity, GST_FORMAT_TIME, - !timidity->o_new_segment); - - GST_LOG_OBJECT (timidity, - "sending newsegment from %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT - ", pos=%" GST_TIME_FORMAT, GST_TIME_ARGS ((guint64) segment->start), - GST_TIME_ARGS ((guint64) segment->stop), - GST_TIME_ARGS ((guint64) segment->time)); - - if (timidity->o_segment->flags & GST_SEEK_FLAG_SEGMENT) { - gst_element_post_message (GST_ELEMENT (timidity), - gst_message_new_segment_start (GST_OBJECT (timidity), - segment->format, segment->start)); - } - - gst_segment_free (segment); - timidity->o_segment_changed = FALSE; - return; - } - - if (timidity->o_seek) { - /* perform a seek internally */ - timidity->o_segment->last_stop = timidity->o_segment->time; - mid_song_seek (timidity->song, - (timidity->o_segment->last_stop * timidity->time_per_frame) / - GST_MSECOND); - } - - out = gst_timidity_get_buffer (timidity); - if (!out) { - GST_LOG_OBJECT (timidity, "Song ended, generating eos"); - gst_pad_push_event (timidity->srcpad, gst_event_new_eos ()); - timidity->o_seek = FALSE; - goto paused; - } - - if (timidity->o_seek) { - GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DISCONT); - timidity->o_seek = FALSE; - } - - gst_buffer_set_caps (out, timidity->out_caps); - ret = gst_pad_push (timidity->srcpad, out); - - if (ret == GST_FLOW_UNEXPECTED) - goto eos; - else if (ret < GST_FLOW_UNEXPECTED || ret == GST_FLOW_NOT_LINKED) - goto error; - - return; - -paused: - { - GST_DEBUG_OBJECT (timidity, "pausing task"); - gst_pad_pause_task (timidity->sinkpad); - return; - } -eos: - { - gst_pad_push_event (timidity->srcpad, gst_event_new_eos ()); - goto paused; - } -error: - { - GST_ELEMENT_FLOW_ERROR (timidity, ret); - gst_pad_push_event (timidity->srcpad, gst_event_new_eos ()); - goto paused; - } -} - -static GstStateChangeReturn -gst_timidity_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstTimidity *timidity = GST_TIMIDITY (element); - - if (!timidity->initialized) { - GST_WARNING ("Timidity renderer is not initialized"); - return GST_STATE_CHANGE_FAILURE; - } - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - timidity->out_caps = - gst_caps_copy (gst_pad_get_pad_template_caps (timidity->srcpad)); - timidity->mididata = NULL; - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - timidity->mididata_size = 0; - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - if (timidity->song) - mid_song_free (timidity->song); - timidity->song = NULL; - timidity->mididata_size = 0; - if (timidity->mididata) { - g_free (timidity->mididata); - timidity->mididata = NULL; - } - break; - case GST_STATE_CHANGE_READY_TO_NULL: - gst_caps_unref (timidity->out_caps); - break; - default: - break; - } - - return ret; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - GST_DEBUG_CATEGORY_INIT (gst_timidity_debug, "timidity", - 0, "Timidity plugin"); - - return gst_element_register (plugin, "timidity", - GST_RANK_PRIMARY, GST_TYPE_TIMIDITY); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - timidity, - "Timidity Plugin", - plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/timidity/gsttimidity.h b/ext/timidity/gsttimidity.h deleted file mode 100644 index 4e9350b73..000000000 --- a/ext/timidity/gsttimidity.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * gsttimdity - timidity plugin for gstreamer - * - * Copyright 2007 Wouter Paesen <wouter@blue-gate.be> - * - * 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. - * - * Wrapper element for libtimidity. This element works in pull - * based mode because that's essentially how libtimidity works. - * We create a libtimidity stream that operates on the srcpad. - * The sinkpad is in pull mode. - */ - -#ifndef __GST_TIMIDITY_H__ -#define __GST_TIMIDITY_H__ - -#include <gst/gst.h> -#include <gst/base/gstadapter.h> -#include <timidity.h> - -G_BEGIN_DECLS -#define GST_TYPE_TIMIDITY \ - (gst_timidity_get_type()) -#define GST_TIMIDITY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TIMIDITY,GstTimidity)) -#define GST_TIMIDITY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TIMIDITY,GstTimidityClass)) -#define GST_IS_TIMIDITY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TIMIDITY)) -#define GST_IS_TIMIDITY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TIMIDITY)) -typedef struct _GstTimidity GstTimidity; -typedef struct _GstTimidityClass GstTimidityClass; - -struct _GstTimidity -{ - GstElement element; - - GstPad *sinkpad, *srcpad; - - gboolean initialized; - - /* input stream properties */ - gint64 mididata_size, mididata_offset; - gchar *mididata; - gboolean mididata_filled; - - MidSong *song; - - /* output data */ - gboolean o_new_segment, o_segment_changed, o_seek; - GstSegment o_segment[1]; - gint64 o_len; - - /* format of the stream */ - MidSongOptions song_options[1]; - gint64 bytes_per_frame; - GstClockTime time_per_frame; - - GstCaps *out_caps; -}; - -struct _GstTimidityClass -{ - GstElementClass parent_class; -}; - -GType gst_timidity_get_type (void); - -G_END_DECLS -#endif /* __GST_TIMIDITY_H__ */ diff --git a/ext/timidity/Makefile.am b/ext/wildmidi/Makefile.am index 9ec7bbd83..7dfdc883f 100644 --- a/ext/timidity/Makefile.am +++ b/ext/wildmidi/Makefile.am @@ -1,20 +1,6 @@ # plugindir is set in configure plugin_LTLIBRARIES = -if USE_TIMIDITY -plugin_LTLIBRARIES += libgsttimidity.la - -# sources used to compile this plug-in -libgsttimidity_la_SOURCES = gsttimidity.c - -# flags used to compile this plugin -# add other _CFLAGS and _LIBS as needed -libgsttimidity_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(TIMIDITY_CFLAGS) -libgsttimidity_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(TIMIDITY_LIBS) -libgsttimidity_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgsttimidity_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) -endif - if USE_WILDMIDI plugin_LTLIBRARIES += libgstwildmidi.la @@ -29,5 +15,5 @@ libgstwildmidi_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstwildmidi_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) endif -noinst_HEADERS = gsttimidity.h gstwildmidi.h +noinst_HEADERS = gstwildmidi.h diff --git a/ext/timidity/README b/ext/wildmidi/README index f883cd002..f883cd002 100644 --- a/ext/timidity/README +++ b/ext/wildmidi/README diff --git a/ext/timidity/gstwildmidi.c b/ext/wildmidi/gstwildmidi.c index 7f380d6da..7f380d6da 100644 --- a/ext/timidity/gstwildmidi.c +++ b/ext/wildmidi/gstwildmidi.c diff --git a/ext/timidity/gstwildmidi.h b/ext/wildmidi/gstwildmidi.h index 54a915b30..54a915b30 100644 --- a/ext/timidity/gstwildmidi.h +++ b/ext/wildmidi/gstwildmidi.h diff --git a/ext/xvid/Makefile.am b/ext/xvid/Makefile.am deleted file mode 100644 index 016f3736a..000000000 --- a/ext/xvid/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -plugin_LTLIBRARIES = libgstxvid.la - -libgstxvid_la_SOURCES = gstxvidenc.c gstxviddec.c gstxvid.c -libgstxvid_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(XVID_CFLAGS) -libgstxvid_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(XVID_LIBS) -libgstxvid_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstxvid_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) - -noinst_HEADERS = gstxvidenc.h gstxviddec.h gstxvid.h diff --git a/ext/xvid/gstxvid.c b/ext/xvid/gstxvid.c deleted file mode 100644 index 9d0d150cc..000000000 --- a/ext/xvid/gstxvid.c +++ /dev/null @@ -1,371 +0,0 @@ -/* GStreamer xvid encoder/decoder plugin - * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * 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 <string.h> -#include <xvid.h> - -#include <gst/video/video.h> -#include "gstxviddec.h" -#include "gstxvidenc.h" - -gboolean -gst_xvid_init (void) -{ - xvid_gbl_init_t xinit; - gint ret; - static gboolean is_init = FALSE; - - /* only init once */ - if (is_init == TRUE) { - return TRUE; - } - - /* set up xvid initially (function pointers, CPU flags) */ - gst_xvid_init_struct (xinit); - - if ((ret = xvid_global (NULL, XVID_GBL_INIT, &xinit, NULL)) < 0) { - g_warning ("Failed to initialize XviD: %s (%d)", gst_xvid_error (ret), ret); - return FALSE; - } - - GST_LOG ("Initted XviD version %d.%d.%d (API %d.%d)", - XVID_VERSION_MAJOR (XVID_VERSION), - XVID_VERSION_MINOR (XVID_VERSION), - XVID_VERSION_PATCH (XVID_VERSION), - XVID_API_MAJOR (XVID_API), XVID_API_MINOR (XVID_API)); - - is_init = TRUE; - return TRUE; -} - -const gchar * -gst_xvid_error (int errorcode) -{ - const gchar *error; - - switch (errorcode) { - case XVID_ERR_FAIL: - error = "Operation failed"; - break; - case 0: - error = "No error"; - break; - case XVID_ERR_MEMORY: - error = "Memory allocation error"; - break; - case XVID_ERR_FORMAT: - error = "File format not supported"; - break; - case XVID_ERR_VERSION: - error = "Structure version not supported"; - break; - default: - error = "Unknown error"; - break; - } - - return error; -} - -gint -gst_xvid_structure_to_csp (GstStructure * structure) -{ - const gchar *mime = gst_structure_get_name (structure); - gint xvid_cs = -1; - - if (!strcmp (mime, "video/x-raw-yuv")) { - guint32 fourcc; - - gst_structure_get_fourcc (structure, "format", &fourcc); - switch (fourcc) { - case GST_MAKE_FOURCC ('I', '4', '2', '0'): - xvid_cs = XVID_CSP_I420; - break; - case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): - xvid_cs = XVID_CSP_YUY2; - break; - case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): - xvid_cs = XVID_CSP_YV12; - break; - case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): - xvid_cs = XVID_CSP_UYVY; - break; - case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): - xvid_cs = XVID_CSP_YVYU; - break; - } - } else { - gint depth, bpp, r_mask; - - gst_structure_get_int (structure, "depth", &depth); - gst_structure_get_int (structure, "bpp", &bpp); - gst_structure_get_int (structure, "red_mask", &r_mask); - - switch (depth) { - case 15: - xvid_cs = XVID_CSP_RGB555; - break; - case 16: - xvid_cs = XVID_CSP_RGB565; - break; - case 24: - if (bpp == 24) { - xvid_cs = XVID_CSP_BGR; - } else { - switch (r_mask) { - case 0xff000000: - xvid_cs = XVID_CSP_RGBA; - break; -#ifdef XVID_CSP_ARGB - case 0x00ff0000: - xvid_cs = XVID_CSP_ARGB; - break; -#endif - case 0x0000ff00: - xvid_cs = XVID_CSP_BGRA; - break; - case 0x000000ff: - xvid_cs = XVID_CSP_ABGR; - break; - } - } - break; - default: - break; - } - - } - - return xvid_cs; -} - -GstCaps * -gst_xvid_csp_to_caps (gint csp, gint w, gint h) -{ - GstStructure *structure = NULL; - - switch (csp) { - case XVID_CSP_RGB555: - case XVID_CSP_RGB565: - case XVID_CSP_BGR: - case XVID_CSP_ABGR: - case XVID_CSP_BGRA: -#ifdef XVID_CSP_ARGB - case XVID_CSP_ARGB: -#endif - case XVID_CSP_RGBA:{ - gint r_mask = 0, b_mask = 0, g_mask = 0, - endianness = 0, bpp = 0, depth = 0; - - switch (csp) { - case XVID_CSP_RGB555: - r_mask = GST_VIDEO_COMP1_MASK_15_INT; - g_mask = GST_VIDEO_COMP2_MASK_15_INT; - b_mask = GST_VIDEO_COMP3_MASK_15_INT; - endianness = G_BYTE_ORDER; - depth = 15; - bpp = 16; - break; - case XVID_CSP_RGB565: - r_mask = GST_VIDEO_COMP1_MASK_16_INT; - g_mask = GST_VIDEO_COMP2_MASK_16_INT; - b_mask = GST_VIDEO_COMP3_MASK_16_INT; - endianness = G_BYTE_ORDER; - depth = 16; - bpp = 16; - break; - case XVID_CSP_BGR: - r_mask = 0x0000ff; - g_mask = 0x00ff00; - b_mask = 0xff0000; - endianness = G_BIG_ENDIAN; - depth = 24; - bpp = 24; - break; - case XVID_CSP_ABGR: - r_mask = 0x000000ff; - g_mask = 0x0000ff00; - b_mask = 0x00ff0000; - endianness = G_BIG_ENDIAN; - depth = 24; - bpp = 32; - break; - case XVID_CSP_BGRA: - r_mask = 0x0000ff00; - g_mask = 0x00ff0000; - b_mask = 0xff000000; - endianness = G_BIG_ENDIAN; - depth = 24; - bpp = 32; - break; -#ifdef XVID_CSP_ARGB - case XVID_CSP_ARGB: - r_mask = 0x00ff0000; - g_mask = 0x0000ff00; - b_mask = 0x000000ff; - endianness = G_BIG_ENDIAN; - depth = 24; - bpp = 32; - break; -#endif - case XVID_CSP_RGBA: - r_mask = 0xff000000; - g_mask = 0x00ff0000; - b_mask = 0x0000ff00; - endianness = G_BIG_ENDIAN; - depth = 24; - bpp = 32; - break; - } - - structure = gst_structure_new ("video/x-raw-rgb", - "width", G_TYPE_INT, w, - "height", G_TYPE_INT, h, - "depth", G_TYPE_INT, depth, - "bpp", G_TYPE_INT, bpp, - "endianness", G_TYPE_INT, endianness, - "red_mask", G_TYPE_INT, r_mask, - "green_mask", G_TYPE_INT, g_mask, - "blue_mask", G_TYPE_INT, b_mask, NULL); - break; - } - - case XVID_CSP_YUY2: - case XVID_CSP_YVYU: - case XVID_CSP_UYVY: - case XVID_CSP_I420: - case XVID_CSP_YV12:{ - guint32 fourcc = 0; - - switch (csp) { - case XVID_CSP_YUY2: - fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'); - break; - case XVID_CSP_YVYU: - fourcc = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'); - break; - case XVID_CSP_UYVY: - fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'); - break; - case XVID_CSP_I420: - fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0'); - break; - case XVID_CSP_YV12: - fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2'); - break; - } - - structure = gst_structure_new ("video/x-raw-yuv", - "width", G_TYPE_INT, w, - "height", G_TYPE_INT, h, "format", GST_TYPE_FOURCC, fourcc, NULL); - break; - } - } - - return gst_caps_new_full (structure, NULL); -} - - -gint -gst_xvid_image_get_size (gint csp, gint width, gint height) -{ - xvid_image_t dummy_im; - - return gst_xvid_image_fill (&dummy_im, NULL, csp, width, height); -} - -gint -gst_xvid_image_fill (xvid_image_t * im, void *ptr, gint csp, - gint width, gint height) -{ - gint stride, h2, size = 0; - - im->csp = csp; - - switch (csp) { - case XVID_CSP_I420: - case XVID_CSP_YV12: - /* planar */ - /* luma */ - stride = GST_ROUND_UP_4 (width); - h2 = GST_ROUND_UP_2 (height); - im->stride[0] = stride; - im->plane[0] = ptr; - /* chroma */ - im->plane[1] = ((guint8 *) im->plane[0]) + (stride * h2); - size += stride * height; - stride = GST_ROUND_UP_8 (width) / 2; - h2 = GST_ROUND_UP_2 (height) / 2; - im->stride[1] = stride; - - im->plane[2] = ((guint8 *) im->plane[1]) + (stride * h2); - im->stride[2] = stride; - size += 2 * (stride * h2); - break; - case XVID_CSP_RGB555: - case XVID_CSP_RGB565: - case XVID_CSP_YUY2: - case XVID_CSP_UYVY: - case XVID_CSP_YVYU: - /* packed */ - stride = GST_ROUND_UP_4 (width * 2); - im->plane[0] = ptr; - im->stride[0] = stride; - size = stride * height; - break; - case XVID_CSP_BGR: - stride = GST_ROUND_UP_4 (width * 3); - im->plane[0] = ptr; - im->stride[0] = stride; - size = stride * height * 2; - break; - case XVID_CSP_ABGR: - case XVID_CSP_BGRA: - case XVID_CSP_RGBA: -#ifdef XVID_CSP_ARGB - case XVID_CSP_ARGB: -#endif - stride = width * 4; - im->plane[0] = ptr; - im->stride[0] = stride; - size = stride * height; - break; - } - - return size; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - return (gst_element_register (plugin, "xvidenc", - GST_RANK_SECONDARY, GST_TYPE_XVIDENC) && - gst_element_register (plugin, "xviddec", - GST_RANK_NONE, GST_TYPE_XVIDDEC)); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - xvid, - "XviD plugin library", plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, - GST_PACKAGE_ORIGIN) diff --git a/ext/xvid/gstxvid.h b/ext/xvid/gstxvid.h deleted file mode 100644 index fd08ba90e..000000000 --- a/ext/xvid/gstxvid.h +++ /dev/null @@ -1,57 +0,0 @@ -/* GStreamer xvid encoder/decoder plugin - * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * 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_XVID_H__ -#define __GST_XVID_H__ - -#include <gst/gst.h> - -G_BEGIN_DECLS - -#define gst_xvid_init_struct(s) \ - do { \ - memset (&s, 0, sizeof(s)); \ - s.version = XVID_VERSION; \ - } while (0); - -#define RGB_24_32_STATIC_CAPS(bpp, r_mask,g_mask,b_mask) \ - "video/x-raw-rgb, " \ - "width = (int) [ 0, MAX ], " \ - "height = (int) [ 0, MAX], " \ - "framerate = (fraction) [ 0, MAX], " \ - "depth = (int) 24, " \ - "bpp = (int) " G_STRINGIFY (bpp) ", " \ - "endianness = (int) BIG_ENDIAN, " \ - "red_mask = (int) " G_STRINGIFY (r_mask) ", " \ - "green_mask = (int) " G_STRINGIFY (g_mask) ", " \ - "blue_mask = (int) " G_STRINGIFY (b_mask) - -extern const gchar *gst_xvid_error (int errorcode); -extern gboolean gst_xvid_init (void); - -extern gint gst_xvid_structure_to_csp (GstStructure *structure); -extern GstCaps * gst_xvid_csp_to_caps (gint csp, gint w, gint h); -extern gint gst_xvid_image_get_size (gint csp, - gint width, gint height); -extern gint gst_xvid_image_fill (xvid_image_t * im, void * ptr, gint csp, - gint width, gint height); - -G_END_DECLS - -#endif /* __GST_XVID_H__ */ diff --git a/ext/xvid/gstxviddec.c b/ext/xvid/gstxviddec.c deleted file mode 100644 index b49cf2fad..000000000 --- a/ext/xvid/gstxviddec.c +++ /dev/null @@ -1,673 +0,0 @@ -/* GStreamer xvid decoder plugin - * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> - * (C) 2006 Mark Nauwelaerts <manauw@skynet.be> - * - * 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 <string.h> -#include <xvid.h> - -#include <gst/video/video.h> -#include "gstxviddec.h" - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-xvid, " - "width = (int) [ 0, MAX ], " - "height = (int) [ 0, MAX ], " "framerate = (fraction) [ 0/1, MAX ]; " - "video/mpeg, " - "mpegversion = (int) 4, " - "systemstream = (boolean) FALSE, " - "width = (int) [ 0, MAX ], " - "height = (int) [ 0, MAX ], " "framerate = (fraction) [ 0/1, MAX ]") - ); - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YUY2, YV12, YVYU, UYVY }") - "; " RGB_24_32_STATIC_CAPS (32, 0x00ff0000, 0x0000ff00, - 0x000000ff) "; " RGB_24_32_STATIC_CAPS (32, 0xff000000, 0x00ff0000, - 0x0000ff00) "; " RGB_24_32_STATIC_CAPS (32, 0x0000ff00, 0x00ff0000, - 0xff000000) "; " RGB_24_32_STATIC_CAPS (32, 0x000000ff, 0x0000ff00, - 0x00ff0000) "; " RGB_24_32_STATIC_CAPS (24, 0x0000ff, 0x00ff00, - 0xff0000) "; " GST_VIDEO_CAPS_RGB_15 "; " GST_VIDEO_CAPS_RGB_16) - ); - -GST_DEBUG_CATEGORY_STATIC (xviddec_debug); -#define GST_CAT_DEFAULT xviddec_debug - -static void gst_xviddec_base_init (GstXvidDecClass * klass); -static void gst_xviddec_class_init (GstXvidDecClass * klass); -static void gst_xviddec_init (GstXvidDec * dec); -static void gst_xviddec_reset (GstXvidDec * dec); -static gboolean gst_xviddec_handle_sink_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_xviddec_chain (GstPad * pad, GstBuffer * buf); -static gboolean gst_xviddec_setcaps (GstPad * pad, GstCaps * caps); -static void gst_xviddec_flush_buffers (GstXvidDec * dec, gboolean send); -static GstStateChangeReturn gst_xviddec_change_state (GstElement * element, - GstStateChange transition); - - -static GstElementClass *parent_class = NULL; - -GType -gst_xviddec_get_type (void) -{ - static GType xviddec_type = 0; - - if (!xviddec_type) { - static const GTypeInfo xviddec_info = { - sizeof (GstXvidDecClass), - (GBaseInitFunc) gst_xviddec_base_init, - NULL, - (GClassInitFunc) gst_xviddec_class_init, - NULL, - NULL, - sizeof (GstXvidDec), - 0, - (GInstanceInitFunc) gst_xviddec_init, - }; - - xviddec_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstXvidDec", &xviddec_info, 0); - } - return xviddec_type; -} - -static void -gst_xviddec_base_init (GstXvidDecClass * klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_static_pad_template (element_class, &sink_template); - gst_element_class_add_static_pad_template (element_class, &src_template); - - gst_element_class_set_static_metadata (element_class, "XviD video decoder", - "Codec/Decoder/Video", - "XviD decoder based on xvidcore", - "Ronald Bultje <rbultje@ronald.bitfreak.net>"); -} - -static void -gst_xviddec_class_init (GstXvidDecClass * klass) -{ - GstElementClass *gstelement_class = (GstElementClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - GST_DEBUG_CATEGORY_INIT (xviddec_debug, "xviddec", 0, "XviD decoder"); - - gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_xviddec_change_state); -} - - -static void -gst_xviddec_init (GstXvidDec * dec) -{ - /* create the sink pad */ - dec->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_pad_set_chain_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_xviddec_chain)); - gst_pad_set_setcaps_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_xviddec_setcaps)); - gst_pad_set_event_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_xviddec_handle_sink_event)); - gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); - - /* create the src pad */ - dec->srcpad = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_use_fixed_caps (dec->srcpad); - gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); - - gst_xviddec_reset (dec); -} - - -static void -gst_xviddec_reset (GstXvidDec * dec) -{ - /* size, etc. */ - dec->width = dec->height = dec->csp = -1; - dec->fps_n = dec->par_n = -1; - dec->fps_d = dec->par_d = 1; - dec->next_ts = dec->next_dur = GST_CLOCK_TIME_NONE; - dec->outbuf_size = 0; - - /* set xvid handle to NULL */ - dec->handle = NULL; - - /* no delayed timestamp to start with */ - dec->have_ts = FALSE; - - /* need keyframe to get going */ - dec->waiting_for_key = TRUE; -} - - -static void -gst_xviddec_unset (GstXvidDec * dec) -{ - /* release XviD decoder */ - xvid_decore (dec->handle, XVID_DEC_DESTROY, NULL, NULL); - dec->handle = NULL; -} - - -static gboolean -gst_xviddec_handle_sink_event (GstPad * pad, GstEvent * event) -{ - GstXvidDec *dec = GST_XVIDDEC (GST_PAD_PARENT (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - gst_xviddec_flush_buffers (dec, TRUE); - break; - case GST_EVENT_FLUSH_STOP: - gst_xviddec_flush_buffers (dec, FALSE); - break; - case GST_EVENT_NEWSEGMENT: - /* don't really mind about the actual segment info, - * but we do need to recover from this possible jump */ - /* FIXME, NEWSEGMENT is not a discontinuity. A decoder - * should clip the output to the segment boundaries. - * Also the rate field of the segment can be used to - * optimize the decoding, like skipping B frames when - * playing at double speed. - * The DISCONT flag on buffers should be used to detect - * discontinuities. - */ - dec->waiting_for_key = TRUE; - break; - default: - break; - } - - return gst_pad_push_event (dec->srcpad, event); -} - - -static gboolean -gst_xviddec_setup (GstXvidDec * dec) -{ - xvid_dec_create_t xdec; - gint ret; - - /* initialise parameters, see xvid documentation */ - gst_xvid_init_struct (xdec); - /* let the decoder handle this, don't trust the container */ - xdec.width = 0; - xdec.height = 0; - xdec.handle = NULL; - - GST_DEBUG_OBJECT (dec, "Initializing xvid decoder with parameters " - "%dx%d@%d", dec->width, dec->height, dec->csp); - - if ((ret = xvid_decore (NULL, XVID_DEC_CREATE, &xdec, NULL)) < 0) { - GST_WARNING_OBJECT (dec, "Initializing xvid decoder failed: %s (%d)", - gst_xvid_error (ret), ret); - return FALSE; - } - - dec->handle = xdec.handle; - - return TRUE; -} - - -static void -gst_xviddec_add_par (GstStructure * structure, - gint mux_par_n, gint mux_par_d, gint dec_par_n, gint dec_par_d) -{ - /* muxer wins if decoder has nothing interesting to offer */ - if (dec_par_n == dec_par_d) { - gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION, - mux_par_n, mux_par_d, NULL); - } else { - gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION, - dec_par_n, dec_par_d, NULL); - } -} - - -/* based on the decoder info, if provided, and xviddec info, - construct a caps and send on to src pad */ -static gboolean -gst_xviddec_negotiate (GstXvidDec * dec, xvid_dec_stats_t * xstats) -{ - gboolean ret; - gint par_width, par_height; - GstCaps *caps; - - /* note: setcaps call with no xstats info, - so definitely need to negotiate then */ - if (xstats && (xstats->type != XVID_TYPE_VOL - || (xstats->type == XVID_TYPE_VOL - && dec->width == xstats->data.vol.width - && dec->height == xstats->data.vol.height))) - return TRUE; - - switch (xstats ? xstats->data.vol.par : XVID_PAR_11_VGA) { - case XVID_PAR_11_VGA: - par_width = par_height = 1; - break; - case XVID_PAR_43_PAL: - case XVID_PAR_43_NTSC: - par_width = 4; - par_height = 3; - break; - case XVID_PAR_169_PAL: - case XVID_PAR_169_NTSC: - par_width = 16; - par_height = 9; - break; - case XVID_PAR_EXT: - default: - par_width = xstats->data.vol.par_width; - par_height = xstats->data.vol.par_height; - } - - caps = gst_xvid_csp_to_caps (dec->csp, dec->width, dec->height); - - /* can only provide framerate if we received one */ - if (dec->fps_n != -1) { - gst_structure_set (gst_caps_get_structure (caps, 0), "framerate", - GST_TYPE_FRACTION, dec->fps_n, dec->fps_d, NULL); - } - - gst_xviddec_add_par (gst_caps_get_structure (caps, 0), - dec->par_n, dec->par_d, par_width, par_height); - - GST_LOG ("setting caps on source pad: %" GST_PTR_FORMAT, caps); - ret = gst_pad_set_caps (dec->srcpad, caps); - gst_caps_unref (caps); - - return ret; -} - -static GstFlowReturn -gst_xviddec_chain (GstPad * pad, GstBuffer * buf) -{ - GstXvidDec *dec; - GstBuffer *outbuf = NULL; - xvid_dec_frame_t xframe; - xvid_dec_stats_t xstats; - gint ret; - guint8 *data, *dupe = NULL; - guint size; - GstFlowReturn fret; - - dec = GST_XVIDDEC (GST_OBJECT_PARENT (pad)); - - if (!dec->handle) - goto not_negotiated; - - fret = GST_FLOW_OK; - - GST_LOG_OBJECT (dec, "Received buffer of time %" GST_TIME_FORMAT - " duration %" GST_TIME_FORMAT ", size %d", - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_SIZE (buf)); - - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) { - /* FIXME: should we do anything here, like flush the decoder? */ - } - - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); - - /* xvidcore overreads the input buffer, we need to alloc some extra padding - * to make things work reliably */ -#define EXTRA_PADDING 16 - if (EXTRA_PADDING > 0) { - dupe = g_malloc (size + EXTRA_PADDING); - memcpy (dupe, data, size); - memset (dupe + size, 0, EXTRA_PADDING); - data = dupe; - } - - do { /* loop needed because xvidcore may return vol information */ - /* decode and so ... */ - gst_xvid_init_struct (xframe); - xframe.general = XVID_LOWDELAY; - xframe.bitstream = (void *) data; - xframe.length = size; - - gst_xvid_init_struct (xstats); - - if (outbuf == NULL) { - fret = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE, - dec->outbuf_size, GST_PAD_CAPS (dec->srcpad), &outbuf); - if (fret != GST_FLOW_OK) - goto done; - } - - gst_xvid_image_fill (&xframe.output, GST_BUFFER_DATA (outbuf), - dec->csp, dec->width, dec->height); - - ret = xvid_decore (dec->handle, XVID_DEC_DECODE, &xframe, &xstats); - if (ret < 0) - goto decode_error; - - GST_LOG_OBJECT (dec, "xvid produced output, type %d, consumed %d", - xstats.type, ret); - - if (xstats.type == XVID_TYPE_VOL) - gst_xviddec_negotiate (dec, &xstats); - - data += ret; - size -= ret; - } while (xstats.type <= 0 && size > 0); - - /* 1 byte is frequently left over */ - if (size > 1) { - GST_WARNING_OBJECT (dec, "decoder did not consume all input"); - } - - /* FIXME, reflow the multiple return exit points */ - if (xstats.type > 0) { /* some real output was produced */ - if (G_UNLIKELY (dec->waiting_for_key)) { - if (xstats.type != XVID_TYPE_IVOP) - goto dropping; - - dec->waiting_for_key = FALSE; - } - /* bframes can cause a delay in frames being returned - non keyframe timestamps can permute a bit between - encode and display order, but should match for keyframes */ - if (dec->have_ts) { - GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts; - GST_BUFFER_DURATION (outbuf) = dec->next_dur; - dec->next_ts = GST_BUFFER_TIMESTAMP (buf); - dec->next_dur = GST_BUFFER_DURATION (buf); - } else { - GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); - GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); - } - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dec->srcpad)); - GST_LOG_OBJECT (dec, "pushing buffer with pts %" GST_TIME_FORMAT - " duration %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf))); - fret = gst_pad_push (dec->srcpad, outbuf); - - } else { /* no real output yet, delay in frames being returned */ - if (G_UNLIKELY (dec->have_ts)) { - GST_WARNING_OBJECT (dec, - "xvid decoder produced no output, but timestamp %" GST_TIME_FORMAT - " already queued", GST_TIME_ARGS (dec->next_ts)); - } else { - dec->have_ts = TRUE; - dec->next_ts = GST_BUFFER_TIMESTAMP (buf); - dec->next_dur = GST_BUFFER_DURATION (buf); - } - gst_buffer_unref (outbuf); - } - -done: - g_free (dupe); - gst_buffer_unref (buf); - - return fret; - - /* ERRORS */ -not_negotiated: - { - GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL), - ("format wasn't negotiated before chain function")); - fret = GST_FLOW_NOT_NEGOTIATED; - goto done; - } -decode_error: - { - /* FIXME: shouldn't error out fatally/properly after N decoding errors? */ - GST_ELEMENT_WARNING (dec, STREAM, DECODE, (NULL), - ("Error decoding xvid frame: %s (%d)", gst_xvid_error (ret), ret)); - if (outbuf) - gst_buffer_unref (outbuf); - goto done; - } -dropping: - { - GST_WARNING_OBJECT (dec, "Dropping non-keyframe (seek/init)"); - if (outbuf) - gst_buffer_unref (outbuf); - goto done; - } -} - - -/* flush xvid encoder buffers caused by bframe usage; - not well tested */ -static void -gst_xviddec_flush_buffers (GstXvidDec * dec, gboolean send) -{ -#if 0 - gint ret; - GstBuffer *outbuf = NULL; - xvid_dec_frame_t xframe; - xvid_dec_stats_t xstats; -#endif - - GST_DEBUG_OBJECT (dec, "flushing buffers with send %d, have_ts %d", - send, dec->have_ts); - - /* no need to flush if there is no delayed time-stamp */ - if (!dec->have_ts) - return; - - /* flushing must reset the timestamp keeping */ - dec->have_ts = FALSE; - - /* also no need to flush if no handle */ - if (!dec->handle) - return; - - /* unlike encoder, decoder does not seem to like flushing, disable for now */ -#if 0 - gst_xvid_init_struct (xframe); - gst_xvid_init_struct (xstats); - - /* init a fake frame to force flushing */ - xframe.bitstream = NULL; - xframe.length = -1; - - ret = gst_xviddec_decode (dec, xframe, &outbuf, &xstats); - GST_DEBUG_OBJECT (dec, "received frame when flushing, type %d, size %d", - xstats.type, ret); - - if (ret > 0 && send) { - /* we have some valid return frame, give it the delayed timestamp and send */ - GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts; - GST_BUFFER_DURATION (outbuf) = dec->next_dur; - - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dec->srcpad)); - gst_pad_push (dec->srcpad, outbuf); - return; - } - - if (outbuf) - gst_buffer_unref (outbuf); -#else - return; -#endif -} - -#if 0 -static GstCaps * -gst_xviddec_src_getcaps (GstPad * pad) -{ - GstXvidDec *dec = GST_XVIDDEC (GST_PAD_PARENT (pad)); - GstCaps *caps; - gint csp[] = { - XVID_CSP_I420, - XVID_CSP_YV12, - XVID_CSP_YUY2, - XVID_CSP_UYVY, - XVID_CSP_YVYU, - XVID_CSP_BGRA, - XVID_CSP_ABGR, - XVID_CSP_RGBA, -#ifdef XVID_CSP_ARGB - XVID_CSP_ARGB, -#endif - XVID_CSP_BGR, - XVID_CSP_RGB555, - XVID_CSP_RGB565, - 0 - }, i; - - if (!GST_PAD_CAPS (dec->sinkpad)) { - GstPadTemplate *templ = gst_static_pad_template_get (&src_template); - - return gst_caps_copy (gst_pad_template_get_caps (templ)); - } - - caps = gst_caps_new_empty (); - for (i = 0; csp[i] != 0; i++) { - GstCaps *one = gst_xvid_csp_to_caps (csp[i], dec->width, - dec->height, dec->fps, dec->par); - - gst_caps_append (caps, one); - } - - return caps; -} -#endif - -static gboolean -gst_xviddec_setcaps (GstPad * pad, GstCaps * caps) -{ - GstXvidDec *dec = GST_XVIDDEC (GST_PAD_PARENT (pad)); - GstStructure *structure; - GstCaps *allowed_caps; - const GValue *val; - - GST_LOG_OBJECT (dec, "caps %" GST_PTR_FORMAT, caps); - - /* if there's something old around, remove it */ - if (dec->handle) { - gst_xviddec_unset (dec); - } - - structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "width", &dec->width); - gst_structure_get_int (structure, "height", &dec->height); - - /* perhaps some fps info */ - val = gst_structure_get_value (structure, "framerate"); - if ((val != NULL) && GST_VALUE_HOLDS_FRACTION (val)) { - dec->fps_n = gst_value_get_fraction_numerator (val); - dec->fps_d = gst_value_get_fraction_denominator (val); - } else { - dec->fps_n = -1; - dec->fps_d = 1; - } - - /* perhaps some par info */ - val = gst_structure_get_value (structure, "pixel-aspect-ratio"); - if (val != NULL && GST_VALUE_HOLDS_FRACTION (val)) { - dec->par_n = gst_value_get_fraction_numerator (val); - dec->par_d = gst_value_get_fraction_denominator (val); - } else { - dec->par_n = 1; - dec->par_d = 1; - } - - /* we try to find the preferred/accept csp */ - allowed_caps = gst_pad_get_allowed_caps (dec->srcpad); - if (!allowed_caps) { - GST_DEBUG_OBJECT (dec, "... but no peer, using template caps"); - /* need to copy because get_allowed_caps returns a ref, - and get_pad_template_caps doesn't */ - allowed_caps = gst_caps_copy (gst_pad_get_pad_template_caps (dec->srcpad)); - } - GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps); - - /* pick the first one ... */ - structure = gst_caps_get_structure (allowed_caps, 0); - val = gst_structure_get_value (structure, "format"); - if (val != NULL && G_VALUE_TYPE (val) == GST_TYPE_LIST) { - GValue temp = { 0, }; - gst_value_init_and_copy (&temp, gst_value_list_get_value (val, 0)); - gst_structure_set_value (structure, "format", &temp); - g_value_unset (&temp); - } - - /* ... and use its info to get the csp */ - dec->csp = gst_xvid_structure_to_csp (structure); - if (dec->csp == -1) { - GST_WARNING_OBJECT (dec, "failed to decide on colorspace, using I420"); - dec->csp = XVID_CSP_I420; - } - - dec->outbuf_size = - gst_xvid_image_get_size (dec->csp, dec->width, dec->height); - - GST_LOG_OBJECT (dec, "csp=%d, outbuf_size=%d", dec->csp, dec->outbuf_size); - - gst_caps_unref (allowed_caps); - - /* now set up xvid ... */ - if (!gst_xviddec_setup (dec)) { - GST_ELEMENT_ERROR (GST_ELEMENT (dec), LIBRARY, INIT, (NULL), (NULL)); - return FALSE; - } - - return gst_xviddec_negotiate (dec, NULL); -} - -static GstStateChangeReturn -gst_xviddec_change_state (GstElement * element, GstStateChange transition) -{ - GstXvidDec *dec = GST_XVIDDEC (element); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_xvid_init ()) - return GST_STATE_CHANGE_FAILURE; - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - goto done; - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_xviddec_flush_buffers (dec, FALSE); - if (dec->handle) { - gst_xviddec_unset (dec); - } - gst_xviddec_reset (dec); - break; - default: - break; - } - -done: - return ret; -} diff --git a/ext/xvid/gstxviddec.h b/ext/xvid/gstxviddec.h deleted file mode 100644 index ac3f0ebb8..000000000 --- a/ext/xvid/gstxviddec.h +++ /dev/null @@ -1,73 +0,0 @@ -/* GStreamer xvid decoder plugin - * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * 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_XVIDDEC_H__ -#define __GST_XVIDDEC_H__ - -#include <gst/gst.h> -#include "gstxvid.h" - -G_BEGIN_DECLS - -#define GST_TYPE_XVIDDEC \ - (gst_xviddec_get_type()) -#define GST_XVIDDEC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_XVIDDEC, GstXvidDec)) -#define GST_XVIDDEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_XVIDDEC, GstXvidDecClass)) -#define GST_IS_XVIDDEC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XVIDDEC)) -#define GST_IS_XVIDDEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XVIDDEC)) - -typedef struct _GstXvidDec GstXvidDec; -typedef struct _GstXvidDecClass GstXvidDecClass; - -struct _GstXvidDec { - GstElement element; - - /* pads */ - GstPad *sinkpad, *srcpad; - - /* xvid handle */ - void *handle; - - /* video (output) settings */ - gint csp; - gint width, height; - gint fps_n, fps_d, par_n, par_d; - gint outbuf_size; - - /* whether in need for keyframe */ - gboolean waiting_for_key; - - /* retain some info on delayed frame */ - gboolean have_ts; - GstClockTime next_ts, next_dur; -}; - -struct _GstXvidDecClass { - GstElementClass parent_class; -}; - -GType gst_xviddec_get_type(void); - -G_END_DECLS - -#endif /* __GST_XVIDDEC_H__ */ diff --git a/ext/xvid/gstxvidenc.c b/ext/xvid/gstxvidenc.c deleted file mode 100644 index edf89b7db..000000000 --- a/ext/xvid/gstxvidenc.c +++ /dev/null @@ -1,1403 +0,0 @@ -/* GStreamer xvid encoder plugin - * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> - * (C) 2006 Mark Nauwelaerts <manauw@skynet.be> - * - * 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. - */ - -/* based on: - * - the original xvidenc (by Ronald Bultje) - * - transcode/mplayer's xvid encoder (by Edouard Gomez) - * - * TODO some documentation (e.g. on properties) - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <string.h> - -#include <xvid.h> - -#include <gst/video/video.h> -#include "gstxvidenc.h" - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YUY2, YV12, YVYU, UYVY }") - "; " RGB_24_32_STATIC_CAPS (32, 0x00ff0000, 0x0000ff00, - 0x000000ff) "; " RGB_24_32_STATIC_CAPS (32, 0xff000000, 0x00ff0000, - 0x0000ff00) "; " RGB_24_32_STATIC_CAPS (32, 0x0000ff00, 0x00ff0000, - 0xff000000) "; " RGB_24_32_STATIC_CAPS (32, 0x000000ff, 0x0000ff00, - 0x00ff0000) "; " RGB_24_32_STATIC_CAPS (24, 0x0000ff, 0x00ff00, - 0xff0000) "; " GST_VIDEO_CAPS_RGB_15 "; " GST_VIDEO_CAPS_RGB_16) - ); - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/mpeg, " - "mpegversion = (int) 4, " - "systemstream = (boolean) FALSE, " - "width = (int) [ 0, MAX ], " - "height = (int) [ 0, MAX ], " - "framerate = (fraction) [ 0/1, MAX ], " - "profile = (string) simple, " - "level = (string) { 0, 1, 2, 3, 4a, 5, 6 };" - "video/mpeg, " - "mpegversion = (int) 4, " - "systemstream = (boolean) FALSE, " - "width = (int) [ 0, MAX ], " - "height = (int) [ 0, MAX ], " - "framerate = (fraction) [ 0/1, MAX ], " - "profile = (string) advanced-real-time-simple, " - "level = (string) { 1, 2, 3, 4 };" - "video/mpeg, " - "mpegversion = (int) 4, " - "systemstream = (boolean) FALSE, " - "width = (int) [ 0, MAX ], " - "height = (int) [ 0, MAX ], " - "framerate = (fraction) [ 0/1, MAX ], " - "profile = (string) advanced-simple, " - "level = (string) { 0, 1, 2, 3, 4 };" - "video/mpeg, " - "mpegversion = (int) 4, " - "systemstream = (boolean) FALSE, " - "width = (int) [ 0, MAX ], " "height = (int) [ 0, MAX ]; " - "video/x-xvid, " - "width = (int) [ 0, MAX ], " - "height = (int) [ 0, MAX ], " "framerate = (fraction) [ 0/1, MAX ];") - ); - - -/* XvidEnc properties */ - -/* maximum property-id */ -static int xvidenc_prop_count; - -/* quark used for named pointer on param specs */ -static GQuark xvidenc_pspec_quark; - -GST_DEBUG_CATEGORY_STATIC (xvidenc_debug); -#define GST_CAT_DEFAULT xvidenc_debug - -static void gst_xvidenc_base_init (GstXvidEncClass * klass); -static void gst_xvidenc_class_init (GstXvidEncClass * klass); -static void gst_xvidenc_init (GstXvidEnc * xvidenc); -static void gst_xvidenc_finalize (GObject * object); -static GstFlowReturn gst_xvidenc_chain (GstPad * pad, GstBuffer * data); -static gboolean gst_xvidenc_setcaps (GstPad * pad, GstCaps * vscapslist); -static GstCaps *gst_xvidenc_getcaps (GstPad * pad); -static void gst_xvidenc_flush_buffers (GstXvidEnc * xvidenc, gboolean send); -static gboolean gst_xvidenc_handle_sink_event (GstPad * pad, GstEvent * event); - -/* properties */ -static void gst_xvidenc_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_xvidenc_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); -static GstStateChangeReturn gst_xvidenc_change_state (GstElement * element, - GstStateChange transition); - -static GstElementClass *parent_class = NULL; - -#define GST_TYPE_XVIDENC_PROFILE (gst_xvidenc_profile_get_type ()) -static GType -gst_xvidenc_profile_get_type (void) -{ - static GType xvidenc_profile_type = 0; - - if (!xvidenc_profile_type) { - static const GEnumValue xvidenc_profiles[] = { - {0, "UNP", "Unrestricted profile"}, - {XVID_PROFILE_S_L0, "S_L0", "Simple profile, L0"}, - {XVID_PROFILE_S_L1, "S_L1", "Simple profile, L1"}, - {XVID_PROFILE_S_L2, "S_L2", "Simple profile, L2"}, - {XVID_PROFILE_S_L3, "S_L3", "Simple profile, L3"}, - {XVID_PROFILE_S_L4a, "S_L4a", "Simple profile, L4a"}, - {XVID_PROFILE_S_L5, "S_L5", "Simple profile, L5"}, - {XVID_PROFILE_S_L6, "S_L6", "Simple profile, L6"}, - {XVID_PROFILE_ARTS_L1, "ARTS_L1", - "Advanced real-time simple profile, L1"}, - {XVID_PROFILE_ARTS_L2, "ARTS_L2", - "Advanced real-time simple profile, L2"}, - {XVID_PROFILE_ARTS_L3, "ARTS_L3", - "Advanced real-time simple profile, L3"}, - {XVID_PROFILE_ARTS_L4, "ARTS_L4", - "Advanced real-time simple profile, L4"}, - {XVID_PROFILE_AS_L0, "AS_L0", "Advanced simple profile, L0"}, - {XVID_PROFILE_AS_L1, "AS_L1", "Advanced simple profile, L1"}, - {XVID_PROFILE_AS_L2, "AS_L2", "Advanced simple profile, L2"}, - {XVID_PROFILE_AS_L3, "AS_L3", "Advanced simple profile, L3"}, - {XVID_PROFILE_AS_L4, "AS_L4", "Advanced simple profile, L4"}, - {0, NULL, NULL}, - }; - - xvidenc_profile_type = - g_enum_register_static ("GstXvidEncProfiles", xvidenc_profiles); - } - - return xvidenc_profile_type; -} - -#define GST_TYPE_XVIDENC_QUANT_TYPE (gst_xvidenc_quant_type_get_type ()) -static GType -gst_xvidenc_quant_type_get_type (void) -{ - static GType xvidenc_quant_type_type = 0; - - if (!xvidenc_quant_type_type) { - static const GEnumValue xvidenc_quant_types[] = { - {0, "H263 quantization", "h263"}, - {XVID_VOL_MPEGQUANT, "MPEG quantization", "mpeg"}, - {0, NULL, NULL}, - }; - - xvidenc_quant_type_type = - g_enum_register_static ("GstXvidEncQuantTypes", xvidenc_quant_types); - } - - return xvidenc_quant_type_type; -} - - -enum -{ - XVIDENC_CBR, - XVIDENC_VBR_PASS1, - XVIDENC_VBR_PASS2, - XVIDENC_QUANT -}; - -#define GST_TYPE_XVIDENC_PASS (gst_xvidenc_pass_get_type ()) -static GType -gst_xvidenc_pass_get_type (void) -{ - static GType xvidenc_pass_type = 0; - - if (!xvidenc_pass_type) { - static const GEnumValue xvidenc_passes[] = { - {XVIDENC_CBR, "Constant Bitrate Encoding", "cbr"}, - {XVIDENC_QUANT, "Constant Quantizer", "quant"}, - {XVIDENC_VBR_PASS1, "VBR Encoding - Pass 1", "pass1"}, - {XVIDENC_VBR_PASS2, "VBR Encoding - Pass 2", "pass2"}, - {0, NULL, NULL}, - }; - - xvidenc_pass_type = - g_enum_register_static ("GstXvidEncPasses", xvidenc_passes); - } - - return xvidenc_pass_type; -} - - -GType -gst_xvidenc_get_type (void) -{ - static GType xvidenc_type = 0; - - if (!xvidenc_type) { - static const GTypeInfo xvidenc_info = { - sizeof (GstXvidEncClass), - (GBaseInitFunc) gst_xvidenc_base_init, - NULL, - (GClassInitFunc) gst_xvidenc_class_init, - NULL, - NULL, - sizeof (GstXvidEnc), - 0, - (GInstanceInitFunc) gst_xvidenc_init, - }; - const GInterfaceInfo preset_interface_info = { - NULL, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - xvidenc_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstXvidEnc", &xvidenc_info, 0); - - g_type_add_interface_static (xvidenc_type, GST_TYPE_PRESET, - &preset_interface_info); - } - return xvidenc_type; -} - -static void -gst_xvidenc_base_init (GstXvidEncClass * klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_static_pad_template (element_class, &sink_template); - gst_element_class_add_static_pad_template (element_class, &src_template); - gst_element_class_set_static_metadata (element_class, "XviD video encoder", - "Codec/Encoder/Video", - "XviD encoder based on xvidcore", - "Ronald Bultje <rbultje@ronald.bitfreak.net>"); -} - -/* add property pspec to klass using the counter count, - * and place info based on struct_type and member as a named pointer - * specified by quark */ -#define gst_xvidenc_add_pspec_full(klass, pspec, count, quark, \ - struct_type, member) \ -G_STMT_START { \ - guint _offset = G_STRUCT_OFFSET (struct_type, member); \ - g_param_spec_set_qdata (pspec, quark, \ - GUINT_TO_POINTER (_offset)); \ - g_object_class_install_property (klass, ++count, pspec); \ -} G_STMT_END - -#define gst_xvidenc_add_pspec(klass, pspec, member) \ - gst_xvidenc_add_pspec_full (klass, pspec, xvidenc_prop_count, \ - xvidenc_pspec_quark, GstXvidEnc, member) - -/* using the above system, property maintenance is centralized here - * (_get_property, _set_property and setting of default value in _init) - * follow automatically, it only remains to actually use it in the code - * (which may include free-ing in finalize) */ - -static void -gst_xvidenc_class_init (GstXvidEncClass * klass) -{ - GstElementClass *gstelement_class; - GObjectClass *gobject_class; - GParamSpec *pspec; - - gobject_class = G_OBJECT_CLASS (klass); - gstelement_class = GST_ELEMENT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - GST_DEBUG_CATEGORY_INIT (xvidenc_debug, "xvidenc", 0, "XviD encoder"); - - gobject_class->finalize = gst_xvidenc_finalize; - - gobject_class->set_property = gst_xvidenc_set_property; - gobject_class->get_property = gst_xvidenc_get_property; - - /* prop handling */ - xvidenc_prop_count = 0; - xvidenc_pspec_quark = g_quark_from_static_string ("xvid-enc-param-spec-data"); - - pspec = g_param_spec_enum ("profile", "Profile", - "XviD/MPEG-4 encoding profile", - GST_TYPE_XVIDENC_PROFILE, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, profile); - - pspec = g_param_spec_enum ("quant-type", "Quantizer Type", - "Quantizer type", GST_TYPE_XVIDENC_QUANT_TYPE, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, quant_type); - - pspec = g_param_spec_enum ("pass", "Encoding pass/type", - "Encoding pass/type", - GST_TYPE_XVIDENC_PASS, XVIDENC_CBR, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, pass); - - pspec = g_param_spec_int ("bitrate", "Bitrate", - "[CBR|PASS2] Target video bitrate (bps)", - 0, G_MAXINT, 1800000, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, bitrate); - - pspec = g_param_spec_int ("quantizer", "Quantizer", - "[QUANT] Quantizer to apply for constant quantizer mode", - 2, 31, 2, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, quant); - - pspec = g_param_spec_string ("statsfile", "Statistics Filename", - "[PASS1|PASS2] Filename to store data for 2-pass encoding", - "xvid-stats.log", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, filename); - - pspec = g_param_spec_int ("max-key-interval", "Max. Key Interval", - "Maximum number of frames between two keyframes (< 0 is in sec)", - -100, G_MAXINT, -10, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, max_key_interval); - - pspec = g_param_spec_boolean ("closed-gop", "Closed GOP", - "Closed GOP", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, closed_gop); - - pspec = g_param_spec_int ("motion", "ME Quality", - "Quality of Motion Estimation", 0, 6, 6, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, motion); - - pspec = g_param_spec_boolean ("me-chroma", "ME Chroma", - "Enable use of Chroma planes for Motion Estimation", - TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, me_chroma); - - pspec = g_param_spec_int ("me-vhq", "ME DCT/Frequency", - "Extent in which to use DCT to minimize encoding length", - 0, 4, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, me_vhq); - - pspec = g_param_spec_boolean ("me-quarterpel", "ME Quarterpel", - "Use quarter pixel precision for motion vector search", - FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, me_quarterpel); - - pspec = g_param_spec_boolean ("lumimasking", "Lumimasking", - "Enable lumimasking - apply more compression to dark or bright areas", - FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, lumimasking); - - pspec = g_param_spec_int ("max-bframes", "Max B-Frames", - "Maximum B-frames in a row", 0, G_MAXINT, 1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, max_bframes); - - pspec = g_param_spec_int ("bquant-ratio", "B-quantizer ratio", - "Ratio in B-frame quantizer computation", 0, 200, 150, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, bquant_ratio); - - pspec = g_param_spec_int ("bquant-offset", "B-quantizer offset", - "Offset in B-frame quantizer computation", - 0, 200, 100, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, bquant_offset); - - pspec = g_param_spec_int ("bframe-threshold", "B-Frame Threshold", - "Higher threshold yields more chance that B-frame is used", - -255, 255, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, bframe_threshold); - - pspec = g_param_spec_boolean ("gmc", "Global Motion Compensation", - "Allow generation of Sprite Frames for Pan/Zoom/Rotating images", - FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, gmc); - - pspec = g_param_spec_boolean ("trellis", "Trellis Quantization", - "Enable Trellis Quantization", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, trellis); - - pspec = g_param_spec_boolean ("interlaced", "Interlaced Material", - "Enable for interlaced video material", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, interlaced); - - pspec = g_param_spec_boolean ("cartoon", "Cartoon Material", - "Adjust thresholds for flat looking cartoons", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, cartoon); - - pspec = g_param_spec_boolean ("greyscale", "Disable Chroma", - "Do not write chroma data in encoded video", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, greyscale); - - pspec = g_param_spec_boolean ("hqacpred", "High quality AC prediction", - "Enable high quality AC prediction", TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, hqacpred); - - pspec = g_param_spec_int ("max-iquant", "Max Quant I-Frames", - "Upper bound for I-frame quantization", 0, 31, 31, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, max_iquant); - - pspec = g_param_spec_int ("min-iquant", "Min Quant I-Frames", - "Lower bound for I-frame quantization", 0, 31, 2, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, min_iquant); - - pspec = g_param_spec_int ("max-pquant", "Max Quant P-Frames", - "Upper bound for P-frame quantization", 0, 31, 31, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, max_pquant); - - pspec = g_param_spec_int ("min-pquant", "Min Quant P-Frames", - "Lower bound for P-frame quantization", 0, 31, 2, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, min_pquant); - - pspec = g_param_spec_int ("max-bquant", "Max Quant B-Frames", - "Upper bound for B-frame quantization", 0, 31, 31, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, max_bquant); - - pspec = g_param_spec_int ("min-bquant", "Min Quant B-Frames", - "Lower bound for B-frame quantization", 0, 31, 2, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, min_bquant); - - pspec = g_param_spec_int ("reaction-delay-factor", "Reaction Delay Factor", - "[CBR] Reaction delay factor", -1, 100, -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, reaction_delay_factor); - - pspec = g_param_spec_int ("averaging-period", "Averaging Period", - "[CBR] Number of frames for which XviD averages bitrate", - -1, 100, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, averaging_period); - - pspec = g_param_spec_int ("buffer", "Buffer Size", - "[CBR] Size of the video buffers", -1, G_MAXINT, -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, buffer); - - pspec = g_param_spec_int ("keyframe-boost", "Keyframe boost", - "[PASS2] Bitrate boost for keyframes", 0, 100, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, keyframe_boost); - - pspec = g_param_spec_int ("curve-compression-high", "Curve Compression High", - "[PASS2] Shrink factor for upper part of bitrate curve", - 0, 100, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, curve_compression_high); - - pspec = g_param_spec_int ("curve-compression-low", "Curve Compression Low", - "[PASS2] Growing factor for lower part of bitrate curve", - 0, 100, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, curve_compression_low); - - pspec = g_param_spec_int ("flow-control-strength", "Flow Control Strength", - "[PASS2] Overflow control strength per frame", - -1, 100, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, overflow_control_strength); - - pspec = - g_param_spec_int ("max-overflow-improvement", "Max Overflow Improvement", - "[PASS2] Amount in % that flow control can increase frame size compared to ideal curve", - -1, 100, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, max_overflow_improvement); - - pspec = - g_param_spec_int ("max-overflow-degradation", "Max Overflow Degradation", - "[PASS2] Amount in % that flow control can decrease frame size compared to ideal curve", - -1, 100, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, max_overflow_degradation); - - pspec = g_param_spec_int ("keyframe-reduction", "Keyframe Reduction", - "[PASS2] Keyframe size reduction in % of those within threshold", - -1, 100, 20, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, kfreduction); - - pspec = g_param_spec_int ("keyframe-threshold", "Keyframe Threshold", - "[PASS2] Distance between keyframes not to be subject to reduction", - -1, 100, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, kfthreshold); - - pspec = - g_param_spec_int ("container-frame-overhead", "Container Frame Overhead", - "[PASS2] Average container overhead per frame", -1, 100, -1, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - gst_xvidenc_add_pspec (gobject_class, pspec, container_frame_overhead); - - gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_xvidenc_change_state); -} - - -static void -gst_xvidenc_init (GstXvidEnc * xvidenc) -{ - GParamSpec **pspecs; - guint i, num_props; - - /* create the sink pad */ - xvidenc->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_element_add_pad (GST_ELEMENT (xvidenc), xvidenc->sinkpad); - - gst_pad_set_chain_function (xvidenc->sinkpad, - GST_DEBUG_FUNCPTR (gst_xvidenc_chain)); - gst_pad_set_setcaps_function (xvidenc->sinkpad, - GST_DEBUG_FUNCPTR (gst_xvidenc_setcaps)); - gst_pad_set_getcaps_function (xvidenc->sinkpad, - GST_DEBUG_FUNCPTR (gst_xvidenc_getcaps)); - gst_pad_set_event_function (xvidenc->sinkpad, - GST_DEBUG_FUNCPTR (gst_xvidenc_handle_sink_event)); - - /* create the src pad */ - xvidenc->srcpad = gst_pad_new_from_static_template (&src_template, "src"); - gst_element_add_pad (GST_ELEMENT (xvidenc), xvidenc->srcpad); - gst_pad_use_fixed_caps (xvidenc->srcpad); - - /* init properties. */ - xvidenc->width = xvidenc->height = xvidenc->csp = -1; - xvidenc->par_width = xvidenc->par_height = 1; - - /* set defaults for user properties */ - pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (xvidenc), - &num_props); - - for (i = 0; i < num_props; ++i) { - GValue val = { 0, }; - GParamSpec *pspec = pspecs[i]; - - /* only touch those that are really ours; i.e. should have some qdata */ - if (!g_param_spec_get_qdata (pspec, xvidenc_pspec_quark)) - continue; - g_value_init (&val, G_PARAM_SPEC_VALUE_TYPE (pspec)); - g_param_value_set_default (pspec, &val); - g_object_set_property (G_OBJECT (xvidenc), g_param_spec_get_name (pspec), - &val); - g_value_unset (&val); - } - - g_free (pspecs); - - /* set xvid handle to NULL */ - xvidenc->handle = NULL; - - /* get a queue to keep time info if frames get delayed */ - xvidenc->delay = NULL; - - /* cache some xvid data so need not rebuild for each frame */ - xvidenc->xframe_cache = NULL; -} - - -static void -gst_xvidenc_finalize (GObject * object) -{ - - GstXvidEnc *xvidenc = GST_XVIDENC (object); - - g_free (xvidenc->filename); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static gboolean -gst_xvidenc_handle_sink_event (GstPad * pad, GstEvent * event) -{ - GstXvidEnc *xvidenc = GST_XVIDENC (GST_PAD_PARENT (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - gst_xvidenc_flush_buffers (xvidenc, TRUE); - break; - /* no flushing if flush received, - buffers in encoder are considered (in the) past */ - default: - break; - } - - return gst_pad_push_event (xvidenc->srcpad, event); -} - -static gboolean -gst_xvidenc_setup (GstXvidEnc * xvidenc) -{ - xvid_enc_create_t xenc; - xvid_enc_plugin_t xplugin[2]; - gint ret; - GstCaps *allowed_caps; - gint profile = -1; - - /* Negotiate profile/level with downstream */ - allowed_caps = gst_pad_get_allowed_caps (xvidenc->srcpad); - if (allowed_caps && !gst_caps_is_empty (allowed_caps)) { - const gchar *profile_str, *level_str; - - allowed_caps = gst_caps_make_writable (allowed_caps); - gst_caps_truncate (allowed_caps); - - profile_str = - gst_structure_get_string (gst_caps_get_structure (allowed_caps, 0), - "profile"); - level_str = - gst_structure_get_string (gst_caps_get_structure (allowed_caps, 0), - "level"); - if (profile_str) { - if (g_str_equal (profile_str, "simple")) { - if (!level_str) { - profile = XVID_PROFILE_S_L0; - } else if (g_str_equal (level_str, "0")) { - profile = XVID_PROFILE_S_L0; - } else if (g_str_equal (level_str, "1")) { - profile = XVID_PROFILE_S_L1; - } else if (g_str_equal (level_str, "2")) { - profile = XVID_PROFILE_S_L2; - } else if (g_str_equal (level_str, "3")) { - profile = XVID_PROFILE_S_L3; - } else if (g_str_equal (level_str, "4a")) { - profile = XVID_PROFILE_S_L4a; - } else if (g_str_equal (level_str, "5")) { - profile = XVID_PROFILE_S_L5; - } else if (g_str_equal (level_str, "6")) { - profile = XVID_PROFILE_S_L6; - } else { - GST_ERROR_OBJECT (xvidenc, - "Invalid profile/level combination (%s %s)", profile_str, - level_str); - } - } else if (g_str_equal (profile_str, "advanced-real-time-simple")) { - if (!level_str) { - profile = XVID_PROFILE_ARTS_L1; - } else if (g_str_equal (level_str, "1")) { - profile = XVID_PROFILE_ARTS_L1; - } else if (g_str_equal (level_str, "2")) { - profile = XVID_PROFILE_ARTS_L2; - } else if (g_str_equal (level_str, "3")) { - profile = XVID_PROFILE_ARTS_L3; - } else if (g_str_equal (level_str, "4")) { - profile = XVID_PROFILE_ARTS_L4; - } else { - GST_ERROR_OBJECT (xvidenc, - "Invalid profile/level combination (%s %s)", profile_str, - level_str); - } - } else if (g_str_equal (profile_str, "advanced-simple")) { - if (!level_str) { - profile = XVID_PROFILE_AS_L0; - } else if (g_str_equal (level_str, "0")) { - profile = XVID_PROFILE_AS_L0; - } else if (g_str_equal (level_str, "1")) { - profile = XVID_PROFILE_AS_L1; - } else if (g_str_equal (level_str, "2")) { - profile = XVID_PROFILE_AS_L2; - } else if (g_str_equal (level_str, "3")) { - profile = XVID_PROFILE_AS_L3; - } else if (g_str_equal (level_str, "4")) { - profile = XVID_PROFILE_AS_L4; - } else { - GST_ERROR_OBJECT (xvidenc, - "Invalid profile/level combination (%s %s)", profile_str, - level_str); - } - } else { - GST_ERROR_OBJECT (xvidenc, "Invalid profile (%s)", profile_str); - } - } - } - if (allowed_caps) - gst_caps_unref (allowed_caps); - - if (profile != -1) { - xvidenc->profile = profile; - g_object_notify (G_OBJECT (xvidenc), "profile"); - } - - /* see xvid.h for the meaning of all this. */ - gst_xvid_init_struct (xenc); - - xenc.profile = xvidenc->used_profile = xvidenc->profile; - xenc.width = xvidenc->width; - xenc.height = xvidenc->height; - xenc.max_bframes = xvidenc->max_bframes; - xenc.global = XVID_GLOBAL_PACKED - | (xvidenc->closed_gop ? XVID_GLOBAL_CLOSED_GOP : 0); - - xenc.bquant_ratio = xvidenc->bquant_ratio; - xenc.bquant_offset = xvidenc->bquant_offset; - - xenc.fbase = xvidenc->fbase; - xenc.fincr = xvidenc->fincr; - xenc.max_key_interval = (xvidenc->max_key_interval < 0) ? - (-xvidenc->max_key_interval * xenc.fbase / - xenc.fincr) : xvidenc->max_key_interval; - xenc.handle = NULL; - - /* quantizer ranges */ - xenc.min_quant[0] = xvidenc->min_iquant; - xenc.min_quant[1] = xvidenc->min_pquant; - xenc.min_quant[2] = xvidenc->min_bquant; - xenc.max_quant[0] = xvidenc->max_iquant; - xenc.max_quant[1] = xvidenc->max_pquant; - xenc.max_quant[2] = xvidenc->max_bquant; - - /* cbr, vbr or constant quantizer */ - xenc.num_plugins = 1; - xenc.plugins = xplugin; - switch (xvidenc->pass) { - case XVIDENC_CBR: - case XVIDENC_QUANT: - { - xvid_plugin_single_t xsingle; - xvid_enc_zone_t xzone; - - gst_xvid_init_struct (xsingle); - - xenc.plugins[0].func = xvid_plugin_single; - xenc.plugins[0].param = &xsingle; - - xsingle.bitrate = xvidenc->bitrate; - xsingle.reaction_delay_factor = MAX (0, xvidenc->reaction_delay_factor); - xsingle.averaging_period = MAX (0, xvidenc->averaging_period); - xsingle.buffer = MAX (0, xvidenc->buffer); - - if (xvidenc->pass == XVIDENC_CBR) - break; - - /* set up a const quantizer zone */ - xzone.mode = XVID_ZONE_QUANT; - xzone.frame = 0; - xzone.increment = xvidenc->quant; - xzone.base = 1; - xenc.zones = &xzone; - xenc.num_zones++; - - break; - } - case XVIDENC_VBR_PASS1: - { - xvid_plugin_2pass1_t xpass; - - gst_xvid_init_struct (xpass); - - xenc.plugins[0].func = xvid_plugin_2pass1; - xenc.plugins[0].param = &xpass; - - xpass.filename = xvidenc->filename; - break; - } - case XVIDENC_VBR_PASS2: - { - xvid_plugin_2pass2_t xpass; - - gst_xvid_init_struct (xpass); - - xenc.plugins[0].func = xvid_plugin_2pass2; - xenc.plugins[0].param = &xpass; - - xpass.bitrate = xvidenc->bitrate; - xpass.filename = xvidenc->filename; - xpass.keyframe_boost = xvidenc->keyframe_boost; - xpass.curve_compression_high = xvidenc->curve_compression_high; - xpass.curve_compression_low = xvidenc->curve_compression_low; - xpass.overflow_control_strength = - MAX (0, xvidenc->overflow_control_strength); - xpass.max_overflow_improvement = - MAX (0, xvidenc->max_overflow_improvement); - xpass.max_overflow_degradation = - MAX (0, xvidenc->max_overflow_degradation); - xpass.kfreduction = MAX (0, xvidenc->kfreduction); - xpass.kfthreshold = MAX (0, xvidenc->kfthreshold); - xpass.container_frame_overhead = - MAX (0, xvidenc->container_frame_overhead); - break; - } - } - - if (xvidenc->lumimasking) { - xenc.plugins[1].func = xvid_plugin_lumimasking; - xenc.plugins[1].param = NULL; - xenc.num_plugins++; - } - - if ((ret = xvid_encore (NULL, XVID_ENC_CREATE, &xenc, NULL)) < 0) { - GST_DEBUG_OBJECT (xvidenc, "Error setting up xvid encoder: %s (%d)", - gst_xvid_error (ret), ret); - return FALSE; - } - - xvidenc->handle = xenc.handle; - - return TRUE; -} - -static gboolean -gst_xvidenc_setcaps (GstPad * pad, GstCaps * vscaps) -{ - GstXvidEnc *xvidenc; - GstStructure *structure; - gint w, h; - const GValue *fps, *par; - gint xvid_cs = -1; - - xvidenc = GST_XVIDENC (GST_PAD_PARENT (pad)); - - /* if there's something old around, remove it */ - if (xvidenc->handle) { - gst_xvidenc_flush_buffers (xvidenc, TRUE); - xvid_encore (xvidenc->handle, XVID_ENC_DESTROY, NULL, NULL); - xvidenc->handle = NULL; - } - - structure = gst_caps_get_structure (vscaps, 0); - - if (!gst_structure_get_int (structure, "width", &w) || - !gst_structure_get_int (structure, "height", &h)) { - return FALSE; - } - - fps = gst_structure_get_value (structure, "framerate"); - if (fps == NULL || !GST_VALUE_HOLDS_FRACTION (fps)) { - GST_WARNING_OBJECT (pad, "no framerate specified, or not a GstFraction"); - return FALSE; - } - - /* optional par info */ - par = gst_structure_get_value (structure, "pixel-aspect-ratio"); - - xvid_cs = gst_xvid_structure_to_csp (structure); - if (xvid_cs == -1) { - gchar *sstr; - - sstr = gst_structure_to_string (structure); - GST_DEBUG_OBJECT (xvidenc, "Did not find xvid colourspace for caps %s", - sstr); - g_free (sstr); - return FALSE; - } - - xvidenc->csp = xvid_cs; - xvidenc->width = w; - xvidenc->height = h; - xvidenc->fbase = gst_value_get_fraction_numerator (fps); - xvidenc->fincr = gst_value_get_fraction_denominator (fps); - if ((par != NULL) && GST_VALUE_HOLDS_FRACTION (par)) { - xvidenc->par_width = gst_value_get_fraction_numerator (par); - xvidenc->par_height = gst_value_get_fraction_denominator (par); - } else { - xvidenc->par_width = 1; - xvidenc->par_height = 1; - } - - /* wipe xframe cache given possible change caps properties */ - g_free (xvidenc->xframe_cache); - xvidenc->xframe_cache = NULL; - - if (gst_xvidenc_setup (xvidenc)) { - gboolean ret = FALSE; - GstCaps *new_caps = NULL, *allowed_caps; - - /* please downstream with preferred caps */ - allowed_caps = gst_pad_get_allowed_caps (xvidenc->srcpad); - GST_DEBUG_OBJECT (xvidenc, "allowed caps: %" GST_PTR_FORMAT, allowed_caps); - - if (allowed_caps && !gst_caps_is_empty (allowed_caps)) { - new_caps = gst_caps_copy_nth (allowed_caps, 0); - } else { - new_caps = gst_caps_new_simple ("video/x-xvid", NULL); - } - if (allowed_caps) - gst_caps_unref (allowed_caps); - - gst_caps_set_simple (new_caps, - "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, - "framerate", GST_TYPE_FRACTION, xvidenc->fbase, xvidenc->fincr, - "pixel-aspect-ratio", GST_TYPE_FRACTION, - xvidenc->par_width, xvidenc->par_height, NULL); - /* just to be sure */ - gst_pad_fixate_caps (xvidenc->srcpad, new_caps); - - if (xvidenc->used_profile != 0) { - switch (xvidenc->used_profile) { - case XVID_PROFILE_S_L0: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple", - "level", G_TYPE_STRING, "0", NULL); - break; - case XVID_PROFILE_S_L1: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple", - "level", G_TYPE_STRING, "1", NULL); - break; - case XVID_PROFILE_S_L2: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple", - "level", G_TYPE_STRING, "2", NULL); - break; - case XVID_PROFILE_S_L3: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple", - "level", G_TYPE_STRING, "3", NULL); - break; - case XVID_PROFILE_S_L4a: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple", - "level", G_TYPE_STRING, "4a", NULL); - break; - case XVID_PROFILE_S_L5: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple", - "level", G_TYPE_STRING, "5", NULL); - break; - case XVID_PROFILE_S_L6: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, "simple", - "level", G_TYPE_STRING, "6", NULL); - break; - case XVID_PROFILE_ARTS_L1: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-real-time-simple", "level", G_TYPE_STRING, "1", NULL); - break; - case XVID_PROFILE_ARTS_L2: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-real-time-simple", "level", G_TYPE_STRING, "2", NULL); - break; - case XVID_PROFILE_ARTS_L3: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-real-time-simple", "level", G_TYPE_STRING, "3", NULL); - break; - case XVID_PROFILE_ARTS_L4: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-real-time-simple", "level", G_TYPE_STRING, "4", NULL); - break; - case XVID_PROFILE_AS_L0: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-simple", "level", G_TYPE_STRING, "0", NULL); - break; - case XVID_PROFILE_AS_L1: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-simple", "level", G_TYPE_STRING, "1", NULL); - break; - case XVID_PROFILE_AS_L2: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-simple", "level", G_TYPE_STRING, "2", NULL); - break; - case XVID_PROFILE_AS_L3: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-simple", "level", G_TYPE_STRING, "3", NULL); - break; - case XVID_PROFILE_AS_L4: - gst_caps_set_simple (new_caps, "profile", G_TYPE_STRING, - "advanced-simple", "level", G_TYPE_STRING, "4", NULL); - break; - default: - g_assert_not_reached (); - break; - } - } - - /* src pad should accept anyway */ - ret = gst_pad_set_caps (xvidenc->srcpad, new_caps); - gst_caps_unref (new_caps); - - if (!ret && xvidenc->handle) { - xvid_encore (xvidenc->handle, XVID_ENC_DESTROY, NULL, NULL); - xvidenc->handle = NULL; - } - return ret; - - } else /* setup did not work out */ - return FALSE; -} - -static GstCaps * -gst_xvidenc_getcaps (GstPad * pad) -{ - GstXvidEnc *xvidenc; - GstPad *peer; - GstCaps *caps; - - /* If we already have caps return them */ - if (GST_PAD_CAPS (pad)) - return gst_caps_ref (GST_PAD_CAPS (pad)); - - xvidenc = GST_XVIDENC (gst_pad_get_parent (pad)); - if (!xvidenc) - return gst_caps_new_empty (); - - peer = gst_pad_get_peer (xvidenc->srcpad); - if (peer) { - const GstCaps *templcaps; - GstCaps *peercaps; - guint i, n; - - peercaps = gst_pad_get_caps (peer); - - /* Translate peercaps to YUV */ - peercaps = gst_caps_make_writable (peercaps); - n = gst_caps_get_size (peercaps); - for (i = 0; i < n; i++) { - GstStructure *s = gst_caps_get_structure (peercaps, i); - - gst_structure_set_name (s, "video/x-raw-yuv"); - gst_structure_remove_field (s, "mpegversion"); - gst_structure_remove_field (s, "systemstream"); - } - - templcaps = gst_pad_get_pad_template_caps (pad); - - caps = gst_caps_intersect (peercaps, templcaps); - gst_caps_unref (peercaps); - gst_object_unref (peer); - peer = NULL; - } else { - caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); - } - - gst_object_unref (xvidenc); - - return caps; -} - -/* encodes frame according to info in xframe; - - buf is input buffer, can be NULL if dummy - - buf is disposed of prior to exit - - resulting buffer is returned, NULL if no encoder output or error -*/ -static inline GstBuffer * -gst_xvidenc_encode (GstXvidEnc * xvidenc, GstBuffer * buf, - xvid_enc_frame_t xframe) -{ - GstBuffer *outbuf; - gint ret; - - /* compressed frame should fit in the rough size of an uncompressed one */ - outbuf = gst_buffer_new_and_alloc (gst_xvid_image_get_size (xvidenc->csp, - xvidenc->width, xvidenc->height)); - - xframe.bitstream = (void *) GST_BUFFER_DATA (outbuf); - xframe.length = GST_BUFFER_SIZE (outbuf); - - /* now provide input image data where-abouts, if needed */ - if (buf) - gst_xvid_image_fill (&xframe.input, GST_BUFFER_DATA (buf), xvidenc->csp, - xvidenc->width, xvidenc->height); - - GST_DEBUG_OBJECT (xvidenc, "encoding frame into buffer of size %d", - GST_BUFFER_SIZE (outbuf)); - ret = xvid_encore (xvidenc->handle, XVID_ENC_ENCODE, &xframe, NULL); - - if (ret < 0) { - /* things can be nasty if we are trying to flush, so don't signal error then */ - if (buf) { - GST_ELEMENT_WARNING (xvidenc, LIBRARY, ENCODE, (NULL), - ("Error encoding xvid frame: %s (%d)", gst_xvid_error (ret), ret)); - gst_buffer_unref (buf); - } - gst_buffer_unref (outbuf); - return NULL; - } else if (ret > 0) { /* make sub-buffer */ - GstBuffer *sub; - - GST_DEBUG_OBJECT (xvidenc, "xvid produced output of size %d", ret); - sub = gst_buffer_create_sub (outbuf, 0, ret); - - /* parent no longer needed, will go away with child buffer */ - gst_buffer_unref (outbuf); - outbuf = sub; - } else { /* encoder did not yet produce something */ - GST_DEBUG_OBJECT (xvidenc, "xvid produced no output"); - gst_buffer_unref (outbuf); - g_queue_push_tail (xvidenc->delay, buf); - return NULL; - } - - /* finish decoration and return */ - if (!(xframe.out_flags & XVID_KEYFRAME)) - GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (xvidenc->srcpad)); - - /* now we need the right buf to take timestamps from; - note that timestamps from a display order input buffer can end up with - another encode order output buffer, but other than this permutation, - the overall time progress is tracked, - and keyframes should have the correct stamp */ - if (!g_queue_is_empty (xvidenc->delay)) { - if (buf) - g_queue_push_tail (xvidenc->delay, buf); - buf = g_queue_pop_head (xvidenc->delay); - } - if (buf) { - GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); - GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); - gst_buffer_unref (buf); - } - - return outbuf; -} - -static GstFlowReturn -gst_xvidenc_chain (GstPad * pad, GstBuffer * buf) -{ - GstXvidEnc *xvidenc = GST_XVIDENC (GST_PAD_PARENT (pad)); - GstBuffer *outbuf; - xvid_enc_frame_t xframe; - - const gint motion_presets[] = { - 0, 0, 0, 0, - XVID_ME_HALFPELREFINE16, - XVID_ME_HALFPELREFINE16 | XVID_ME_ADVANCEDDIAMOND16, - XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 - | XVID_ME_HALFPELREFINE8 | XVID_ME_USESQUARES16 - }; - - if (!xvidenc->handle) { - GST_ELEMENT_ERROR (xvidenc, CORE, NEGOTIATION, (NULL), - ("format wasn't negotiated before chain function")); - gst_buffer_unref (buf); - return GST_FLOW_NOT_NEGOTIATED; - } - - GST_DEBUG_OBJECT (xvidenc, - "Received buffer of time %" GST_TIME_FORMAT ", size %d", - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_SIZE (buf)); - - if (xvidenc->xframe_cache) - memcpy (&xframe, xvidenc->xframe_cache, sizeof (xframe)); - else { /* need to build some inital xframe to be cached */ - /* encode and so ... */ - gst_xvid_init_struct (xframe); - - if (xvidenc->par_width == xvidenc->par_height) - xframe.par = XVID_PAR_11_VGA; - else { - xframe.par = XVID_PAR_EXT; - xframe.par_width = xvidenc->par_width; - xframe.par_height = xvidenc->par_height; - } - - /* handle options */ - xframe.vol_flags |= xvidenc->quant_type; - xframe.vop_flags = XVID_VOP_HALFPEL; - xframe.motion = motion_presets[xvidenc->motion]; - - if (xvidenc->me_chroma) { - xframe.motion |= XVID_ME_CHROMA_PVOP; - xframe.motion |= XVID_ME_CHROMA_BVOP; - } - - if (xvidenc->me_vhq >= 1) { - xframe.vop_flags |= XVID_VOP_MODEDECISION_RD; - } - if (xvidenc->me_vhq >= 2) { - xframe.motion |= XVID_ME_HALFPELREFINE16_RD; - xframe.motion |= XVID_ME_QUARTERPELREFINE16_RD; - } - if (xvidenc->me_vhq >= 3) { - xframe.motion |= XVID_ME_HALFPELREFINE8_RD; - xframe.motion |= XVID_ME_QUARTERPELREFINE8_RD; - xframe.motion |= XVID_ME_CHECKPREDICTION_RD; - } - if (xvidenc->me_vhq >= 4) { - xframe.motion |= XVID_ME_EXTSEARCH_RD; - } - - /* no motion estimation, then only intra */ - if (xvidenc->motion == 0) { - xframe.type = XVID_TYPE_IVOP; - } else { - xframe.type = XVID_TYPE_AUTO; - } - - if (xvidenc->motion > 4) { - xframe.vop_flags |= XVID_VOP_INTER4V; - } - - if (xvidenc->me_quarterpel) { - xframe.vol_flags |= XVID_VOL_QUARTERPEL; - xframe.motion |= XVID_ME_QUARTERPELREFINE16; - xframe.motion |= XVID_ME_QUARTERPELREFINE8; - } - - if (xvidenc->gmc) { - xframe.vol_flags |= XVID_VOL_GMC; - xframe.motion |= XVID_ME_GME_REFINE; - } - - if (xvidenc->interlaced) { - xframe.vol_flags |= XVID_VOL_INTERLACING; - } - - if (xvidenc->trellis) { - xframe.vop_flags |= XVID_VOP_TRELLISQUANT; - } - - if (xvidenc->hqacpred) { - xframe.vop_flags |= XVID_VOP_HQACPRED; - } - - if (xvidenc->greyscale) { - xframe.vop_flags |= XVID_VOP_GREYSCALE; - } - - if (xvidenc->cartoon) { - xframe.vop_flags |= XVID_VOP_CARTOON; - xframe.motion |= XVID_ME_DETECT_STATIC_MOTION; - } - - xframe.bframe_threshold = xvidenc->bframe_threshold; - xframe.input.csp = xvidenc->csp; - - /* save in cache */ - xvidenc->xframe_cache = g_memdup (&xframe, sizeof (xframe)); - } - - outbuf = gst_xvidenc_encode (xvidenc, buf, xframe); - - if (!outbuf) /* error or no data yet */ - return GST_FLOW_OK; - - /* go out, multiply! */ - return gst_pad_push (xvidenc->srcpad, outbuf); -} - -/* flush xvid encoder buffers caused by bframe usage */ -static void -gst_xvidenc_flush_buffers (GstXvidEnc * xvidenc, gboolean send) -{ - GstBuffer *outbuf; - xvid_enc_frame_t xframe; - - /* no need to flush if no handle */ - if (!xvidenc->handle) - return; - - gst_xvid_init_struct (xframe); - - /* init a fake frame to force flushing */ - xframe.input.csp = XVID_CSP_NULL; - xframe.input.plane[0] = NULL; - xframe.input.plane[1] = NULL; - xframe.input.plane[2] = NULL; - xframe.input.stride[0] = 0; - xframe.input.stride[1] = 0; - xframe.input.stride[2] = 0; - xframe.quant = 0; - - GST_DEBUG ("flushing buffers with sending %d", send); - - while (!g_queue_is_empty (xvidenc->delay)) { - outbuf = gst_xvidenc_encode (xvidenc, NULL, xframe); - - if (outbuf) { - if (send) - gst_pad_push (xvidenc->srcpad, outbuf); - else - gst_buffer_unref (outbuf); - } else /* hm, there should have been something in there */ - break; - } - - /* our queue should be empty anyway if we did not have to break out ... */ - while (!g_queue_is_empty (xvidenc->delay)) - gst_buffer_unref (g_queue_pop_head (xvidenc->delay)); -} - -static void -gst_xvidenc_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec) -{ - GstXvidEnc *xvidenc; - guint offset; - - xvidenc = GST_XVIDENC (object); - - if (prop_id > xvidenc_prop_count) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - return; - } - - /* our param specs should have such qdata */ - offset = - GPOINTER_TO_UINT (g_param_spec_get_qdata (pspec, xvidenc_pspec_quark)); - - if (offset == 0) - return; - - switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) { - case G_TYPE_BOOLEAN: - G_STRUCT_MEMBER (gboolean, xvidenc, offset) = g_value_get_boolean (value); - break; - case G_TYPE_INT: - G_STRUCT_MEMBER (gint, xvidenc, offset) = g_value_get_int (value); - break; - case G_TYPE_STRING: - g_free (G_STRUCT_MEMBER (gchar *, xvidenc, offset)); - G_STRUCT_MEMBER (gchar *, xvidenc, offset) = g_value_dup_string (value); - break; - default: /* must be enum, given the check above */ - if (G_IS_PARAM_SPEC_ENUM (pspec)) { - G_STRUCT_MEMBER (gint, xvidenc, offset) = g_value_get_enum (value); - } else { - G_STRUCT_MEMBER (guint, xvidenc, offset) = g_value_get_flags (value); - } - break; - } -} - -static void -gst_xvidenc_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - GstXvidEnc *xvidenc; - guint offset; - - xvidenc = GST_XVIDENC (object); - - if (prop_id > xvidenc_prop_count) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - return; - } - - /* our param specs should have such qdata */ - offset = - GPOINTER_TO_UINT (g_param_spec_get_qdata (pspec, xvidenc_pspec_quark)); - - if (offset == 0) - return; - - switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) { - case G_TYPE_BOOLEAN: - g_value_set_boolean (value, G_STRUCT_MEMBER (gboolean, xvidenc, offset)); - break; - case G_TYPE_INT: - g_value_set_int (value, G_STRUCT_MEMBER (gint, xvidenc, offset)); - break; - case G_TYPE_STRING: - g_value_take_string (value, - g_strdup (G_STRUCT_MEMBER (gchar *, xvidenc, offset))); - break; - default: /* must be enum, given the check above */ - if (G_IS_PARAM_SPEC_ENUM (pspec)) { - g_value_set_enum (value, G_STRUCT_MEMBER (gint, xvidenc, offset)); - } else if (G_IS_PARAM_SPEC_FLAGS (pspec)) { - g_value_set_flags (value, G_STRUCT_MEMBER (guint, xvidenc, offset)); - } else { /* oops, bit lazy we don't cover this case yet */ - g_critical ("%s does not yet support type %s", GST_FUNCTION, - g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec))); - } - break; - } -} - -static GstStateChangeReturn -gst_xvidenc_change_state (GstElement * element, GstStateChange transition) -{ - GstXvidEnc *xvidenc = GST_XVIDENC (element); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_xvid_init ()) - return GST_STATE_CHANGE_FAILURE; - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - xvidenc->delay = g_queue_new (); - break; - default: - break; - } - - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - goto done; - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - if (xvidenc->handle) { - gst_xvidenc_flush_buffers (xvidenc, FALSE); - xvid_encore (xvidenc->handle, XVID_ENC_DESTROY, NULL, NULL); - xvidenc->handle = NULL; - } - g_queue_free (xvidenc->delay); - xvidenc->delay = NULL; - g_free (xvidenc->xframe_cache); - xvidenc->xframe_cache = NULL; - break; - default: - break; - } - -done: - return ret; -} diff --git a/ext/xvid/gstxvidenc.h b/ext/xvid/gstxvidenc.h deleted file mode 100644 index ff77aa26c..000000000 --- a/ext/xvid/gstxvidenc.h +++ /dev/null @@ -1,137 +0,0 @@ -/* GStreamer xvid encoder plugin - * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net> - * - * 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_XVIDENC_H__ -#define __GST_XVIDENC_H__ - -#include <gst/gst.h> -#include "gstxvid.h" - -G_BEGIN_DECLS - -#define GST_TYPE_XVIDENC \ - (gst_xvidenc_get_type()) -#define GST_XVIDENC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_XVIDENC, GstXvidEnc)) -#define GST_XVIDENC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_XVIDENC, GstXvidEncClass)) -#define GST_IS_XVIDENC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XVIDENC)) -#define GST_IS_XVIDENC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XVIDENC)) - -typedef struct _GstXvidEnc GstXvidEnc; -typedef struct _GstXvidEncClass GstXvidEncClass; - -struct _GstXvidEnc { - GstElement element; - - /* pads */ - GstPad *sinkpad, *srcpad; - - /* xvid handle */ - void *handle; - - /* cache in place */ - xvid_enc_frame_t *xframe_cache; - - /* caps information */ - gint csp; - gint width, height; - gint fbase; - gint fincr; - gint par_width; - gint par_height; - - /* delayed buffers if bframe usage */ - GQueue *delay; - - /* encoding profile */ - gint profile; - gint used_profile; - - /* quantizer type; h263, MPEG */ - gint quant_type; - - /* encoding type; cbr, vbr, quant */ - gint pass; - - /* quality of encoded image */ - gint bitrate; - gint quant; - - /* gop */ - gint max_key_interval; - gboolean closed_gop; - - /* motion estimation */ - gint motion; - gboolean me_chroma; - gint me_vhq; - gboolean me_quarterpel; - - /* lumimasking */ - gboolean lumimasking; - - /* b-frames */ - gint max_bframes; - gint bquant_ratio; - gint bquant_offset; - gint bframe_threshold; - - /* misc */ - gboolean gmc; - gboolean trellis; - gboolean interlaced; - gboolean cartoon; - gboolean greyscale; - gboolean hqacpred; - - /* quantizer ranges */ - gint max_iquant, min_iquant; - gint max_pquant, min_pquant; - gint max_bquant, min_bquant; - - /* cbr (single pass) encoding */ - gint reaction_delay_factor; - gint averaging_period; - gint buffer; - - /* vbr (2pass) encoding */ - gchar *filename; - gint keyframe_boost; - gint curve_compression_high; - gint curve_compression_low; - gint overflow_control_strength; - gint max_overflow_improvement; - gint max_overflow_degradation; - gint kfreduction; - gint kfthreshold; - gint container_frame_overhead; -}; - -struct _GstXvidEncClass { - GstElementClass parent_class; -}; - -GType gst_xvidenc_get_type(void); - -G_END_DECLS - -#endif /* __GST_XVIDENC_H__ */ |