Index: acconfig.h =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/acconfig.h,v retrieving revision 1.24 diff -c -r1.24 acconfig.h *** acconfig.h 2001/04/27 20:31:22 1.24 --- acconfig.h 2001/05/16 14:25:30 *************** *** 31,36 **** --- 31,37 ---- #undef HAVE_VORBIS #undef HAVE_LIBMAD #undef HAVE_LIBJPEG + #undef HAVE_LIBSDL #undef HAVE_LIBHERMES #undef HAVE_NASM #undef HAVE_MPEG2DEC Index: configure.in =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/configure.in,v retrieving revision 1.145 diff -c -r1.145 configure.in *** configure.in 2001/04/30 20:40:16 1.145 --- configure.in 2001/05/16 14:25:31 *************** *** 452,457 **** --- 452,461 ---- AC_CHECK_LIB(aa, aa_init, HAVE_LIBAA=yes, HAVE_LIBAA=no, ) AC_CHECK_HEADER(aalib.h, :, HAVE_LIBAA=no) + dnl Check for SDLlib + AC_MSG_CHECKING(SDLlib) + AC_CHECK_LIB(SDL, SDL_Init, HAVE_LIBSDL=yes, HAVE_LIBSDL=no, -L/usr/lib -L/usr/local/lib -lpthread) + AC_CHECK_HEADER(SDL/SDL.h, :, HAVE_LIBSDL=no) dnl check if css-auth.c exists (FIXME) AC_MSG_CHECKING(DVD CSS code) *************** *** 704,709 **** --- 708,717 ---- AC_DEFINE(HAVE_LIBJPEG) fi + if test "x$HAVE_LIBSDL" = xyes; then + AC_DEFINE(HAVE_LIBSDL) + fi + if test "x$HAVE_LIBHERMES" = "xyes"; then AC_DEFINE(HAVE_LIBHERMES) fi *************** *** 743,748 **** --- 751,757 ---- AM_CONDITIONAL(HAVE_CSSAUTH, test "x$HAVE_CSSAUTH" = "xyes") AM_CONDITIONAL(HAVE_VORBIS, test "x$HAVE_VORBIS" = "xyes") AM_CONDITIONAL(HAVE_LIBJPEG, test "x$HAVE_LIBJPEG" = "xyes") + AM_CONDITIONAL(HAVE_LIBSDL, test "x$HAVE_LIBSDL" = "xyes") AM_CONDITIONAL(HAVE_LIBHERMES, test "x$HAVE_LIBHERMES" = "xyes") AM_CONDITIONAL(HAVE_NASM, test "x$HAVE_NASM" = "xyes") AM_CONDITIONAL(HAVE_LIBGLADE_GNOME, test "x$HAVE_LIBGLADE_GNOME" = "xyes") *************** *** 942,947 **** --- 951,957 ---- plugins/xmms/Makefile plugins/arts/Makefile plugins/1394/Makefile + plugins/sdlsink/Makefile plugins/dv/Makefile gstplay/Makefile dnl components/bonobo-gstmediaplay/Makefile Index: plugins/Makefile.am =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/plugins/Makefile.am,v retrieving revision 1.42 diff -c -r1.42 Makefile.am *** plugins/Makefile.am 2001/04/23 23:16:12 1.42 --- plugins/Makefile.am 2001/05/16 14:25:32 *************** *** 88,93 **** --- 88,99 ---- AA_SUBDS = endif + if HAVE_LIBSDL + SDL_SUBDS = sdlsink + else + SDL_SUBDS = + endif + if HAVE_LINUX_CDROM LINUX_CDROM_SUBDS = vcdsrc else *************** *** 107,113 **** $(VORBIS_SUBDS) $(DVD_SUBDS) $(ESD_SUBDS) $(ARTSD_SUBDS) \ $(OSS_SUBDS) $(XMMS_SUBDS) $(ALSA_SUBDS) $(RTP_SUBDS) $(ARTS_SUBDS) \ $(RAW1394_SUBDS) $(DV_SUBDS) $(LINUX_CDROM_SUBDS) $(LINUX_VIDEODEV_SUBDS) \ ! $(AA_SUBDS) DIST_SUBDIRS = au wav mp3decode effects visualization mpeg2 mpeg1 \ rtjpeg jpeg mpeg1video videoscale \ --- 113,119 ---- $(VORBIS_SUBDS) $(DVD_SUBDS) $(ESD_SUBDS) $(ARTSD_SUBDS) \ $(OSS_SUBDS) $(XMMS_SUBDS) $(ALSA_SUBDS) $(RTP_SUBDS) $(ARTS_SUBDS) \ $(RAW1394_SUBDS) $(DV_SUBDS) $(LINUX_CDROM_SUBDS) $(LINUX_VIDEODEV_SUBDS) \ ! $(AA_SUBDS) $(SDL_SUBDS) DIST_SUBDIRS = au wav mp3decode effects visualization mpeg2 mpeg1 \ rtjpeg jpeg mpeg1video videoscale \ *** plugins/sdlsink/Makefile.am Thu Aug 24 11:00:32 2000 --- plugins/sdlsink/Makefile.am Wed May 16 16:13:31 2001 *************** *** 0 **** --- 1,21 ---- + filterdir = $(libdir)/gst + + filter_LTLIBRARIES = libsdlsink.la + + if HAVE_LIBSDL + GSTSDLLIBS = -L/usr/lib -L/usr/local/lib -lSDL -lpthread + else + GSTSDLLIBS = + endif + + libsdlsink_la_SOURCES = sdlsink.c + + noinst_HEADERS = sdlsink.h + + check_PROGRAMS = imagetest + + CFLAGS += -O3 -ffast-math -finline-functions -I/usr/include/SDL -I/usr/local/include/SDL -D_REENTRANT + + libsdlsink_la_LIBADD = $(GLIB_LIBS) $(GSTSDLLIBS) + + EXTRA_DIST = README *** plugins/sdlsink/sdlsink.c Thu Aug 24 11:00:32 2000 --- plugins/sdlsink/sdlsink.c Wed May 16 16:20:11 2001 *************** *** 0 **** --- 1,385 ---- + /* GStreamer SDL plugin + * Copyright (C) 2001 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + /* let's not forget to mention that all this was based on aasink ;-) */ + + #include + #include + #include + #include + + #include "sdlsink.h" + + static GstElementDetails gst_sdlsink_details = { + "Video sink", + "Sink/Video", + "An SDL-based videosink", + VERSION, + "Ronald Bultje ", + "(C) 2001", + }; + + /* sdlsink signals and args */ + enum { + SIGNAL_FRAME_DISPLAYED, + SIGNAL_HAVE_SIZE, + LAST_SIGNAL + }; + + + enum { + ARG_0, + ARG_WIDTH, + ARG_HEIGHT, + ARG_DRIVER, + ARG_DITHER, + ARG_BRIGHTNESS, + ARG_CONTRAST, + ARG_GAMMA, + ARG_INVERSION, + ARG_RANDOMVAL, + ARG_FRAMES_DISPLAYED, + ARG_FRAME_TIME, + }; + + GST_PADTEMPLATE_FACTORY (sink_template, + "sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_CAPS_NEW ( + "sdlsink_caps", + "video/raw", + "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("I420")) + ) + ) + + static void gst_sdlsink_class_init (GstSDLSinkClass *klass); + static void gst_sdlsink_init (GstSDLSink *sdlsink); + + static void gst_sdlsink_chain (GstPad *pad, GstBuffer *buf); + + static void gst_sdlsink_set_arg (GtkObject *object, GtkArg *arg, guint id); + static void gst_sdlsink_get_arg (GtkObject *object, GtkArg *arg, guint id); + static void gst_sdlsink_close (GstSDLSink *sdlsink); + static GstElementStateReturn gst_sdlsink_change_state (GstElement *element); + + static GstElementClass *parent_class = NULL; + static guint gst_sdlsink_signals[LAST_SIGNAL] = { 0 }; + + GtkType + gst_sdlsink_get_type (void) + { + static GtkType sdlsink_type = 0; + + if (!sdlsink_type) { + static const GtkTypeInfo sdlsink_info = { + "GstSDLSink", + sizeof(GstSDLSink), + sizeof(GstSDLSinkClass), + (GtkClassInitFunc)gst_sdlsink_class_init, + (GtkObjectInitFunc)gst_sdlsink_init, + (GtkArgSetFunc)gst_sdlsink_set_arg, + (GtkArgGetFunc)gst_sdlsink_get_arg, + (GtkClassInitFunc)NULL, + }; + sdlsink_type = gtk_type_unique(GST_TYPE_ELEMENT,&sdlsink_info); + } + return sdlsink_type; + } + + static void + gst_sdlsink_class_init (GstSDLSinkClass *klass) + { + GtkObjectClass *gtkobject_class; + GstElementClass *gstelement_class; + + gtkobject_class = (GtkObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = gtk_type_class (GST_TYPE_ELEMENT); + + gtk_object_add_arg_type ("GstSDLSink::width", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("GstSDLSink::height", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_HEIGHT); + gtk_object_add_arg_type ("GstSDLSink::brightness", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_BRIGHTNESS); + gtk_object_add_arg_type ("GstSDLSink::contrast", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_CONTRAST); + gtk_object_add_arg_type ("GstSDLSink::gamma", GTK_TYPE_FLOAT, + GTK_ARG_READWRITE, ARG_GAMMA); + gtk_object_add_arg_type ("GstSDLSink::inversion", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_INVERSION); + gtk_object_add_arg_type ("GstSDLSink::randomval", GTK_TYPE_INT, + GTK_ARG_READWRITE, ARG_RANDOMVAL); + gtk_object_add_arg_type ("GstSDLSink::frames_displayed", GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_FRAMES_DISPLAYED); + gtk_object_add_arg_type ("GstSDLSink::frame_time", GTK_TYPE_INT, + GTK_ARG_READABLE, ARG_FRAME_TIME); + + gtkobject_class->set_arg = gst_sdlsink_set_arg; + gtkobject_class->get_arg = gst_sdlsink_get_arg; + + gst_sdlsink_signals[SIGNAL_FRAME_DISPLAYED] = + gtk_signal_new ("frame_displayed", GTK_RUN_LAST, gtkobject_class->type, + GTK_SIGNAL_OFFSET (GstSDLSinkClass, frame_displayed), + gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); + gst_sdlsink_signals[SIGNAL_HAVE_SIZE] = + gtk_signal_new ("have_size", GTK_RUN_LAST, gtkobject_class->type, + GTK_SIGNAL_OFFSET (GstSDLSinkClass, have_size), + gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, + GTK_TYPE_UINT, GTK_TYPE_UINT); + + gtk_object_class_add_signals (gtkobject_class, gst_sdlsink_signals, + LAST_SIGNAL); + + gstelement_class->change_state = gst_sdlsink_change_state; + } + + static void + gst_sdlsink_newcaps (GstPad *pad, GstCaps *caps) + { + GstSDLSink *sdlsink; + gulong print_format; + + sdlsink = GST_SDLSINK (gst_pad_get_parent (pad)); + + sdlsink->width = gst_caps_get_int (caps, "width"); + sdlsink->height = gst_caps_get_int (caps, "height"); + + print_format = GULONG_FROM_LE (sdlsink->format); + + sdlsink->screen = SDL_SetVideoMode(sdlsink->width, sdlsink->height, + 0, SDL_SWSURFACE); + if ( sdlsink->screen == NULL /* || sdlsink->buffer == NULL */) { + GST_ERROR(0, "SDL: Couldn't set %dx%d: %s", sdlsink->width, + sdlsink->height, SDL_GetError()); + printf("error\n"); + return; + } + else { + GST_DEBUG(0, "SDL: Set %dx%d @ %d bpp\n", sdlsink->width, + sdlsink->height, sdlsink->screen->format->BitsPerPixel); + } + + sdlsink->yuv_overlay = SDL_CreateYUVOverlay(sdlsink->width, sdlsink->height, + SDL_IYUV_OVERLAY, sdlsink->screen); + if ( sdlsink->yuv_overlay == NULL ) { + GST_ERROR(0, "SDL: Couldn't create SDL_yuv_overlay: %s\n", SDL_GetError()); + return; + } + + sdlsink->rect.x = 0; + sdlsink->rect.y = 0; + sdlsink->rect.w = sdlsink->width; + sdlsink->rect.h = sdlsink->height; + SDL_DisplayYUVOverlay(sdlsink->yuv_overlay, &(sdlsink->rect)); + + /* make stupid SDL *not* react on SIGINT */ + signal(SIGINT, SIG_DFL); + + GST_DEBUG (0, "sdlsink: setting %08lx (%4.4s)\n", sdlsink->format, (gchar*)&print_format); + + gtk_signal_emit (GTK_OBJECT (sdlsink), gst_sdlsink_signals[SIGNAL_HAVE_SIZE], + sdlsink->width, sdlsink->height); + } + + static void + gst_sdlsink_init (GstSDLSink *sdlsink) + { + sdlsink->sinkpad = gst_pad_new_from_template ( + GST_PADTEMPLATE_GET (sink_template), "sink"); + gst_element_add_pad (GST_ELEMENT (sdlsink), sdlsink->sinkpad); + gst_pad_set_chain_function (sdlsink->sinkpad, gst_sdlsink_chain); + gst_pad_set_newcaps_function (sdlsink->sinkpad, gst_sdlsink_newcaps); + + sdlsink->clock = gst_clock_get_system(); + gst_clock_register(sdlsink->clock, GST_OBJECT(sdlsink)); + + sdlsink->width = -1; + sdlsink->height = -1; + + GST_FLAG_SET(sdlsink, GST_ELEMENT_THREAD_SUGGESTED); + } + + static void + gst_sdlsink_chain (GstPad *pad, GstBuffer *buf) + { + GstSDLSink *sdlsink; + GstClockTimeDiff jitter; + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + sdlsink = GST_SDLSINK (gst_pad_get_parent (pad)); + + if (!GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLUSH)) { + GST_DEBUG (0,"videosink: clock wait: %llu\n", GST_BUFFER_TIMESTAMP(buf)); + + jitter = gst_clock_current_diff(sdlsink->clock, GST_BUFFER_TIMESTAMP (buf)); + + if (jitter > 500000 || jitter < -500000) + { + GST_DEBUG (0, "jitter: %lld\n", jitter); + gst_clock_set (sdlsink->clock, GST_BUFFER_TIMESTAMP (buf)); + } + else { + gst_clock_wait(sdlsink->clock, GST_BUFFER_TIMESTAMP(buf), GST_OBJECT(sdlsink)); + } + } + + /* Lock SDL/yuv-overlay */ + if ( SDL_LockSurface(sdlsink->screen) < 0 ) { + GST_ERROR(0, "SDL_LockSurface(sdlsink->screen) < 0"); + return; + } + if (SDL_LockYUVOverlay(sdlsink->yuv_overlay) < 0) { + GST_ERROR(0, "SDL_LockYUVOverlay(sdlsink->yuv_overlay) < 0"); + return; + } + + /* buf->yuv */ + sdlsink->yuv[0] = GST_BUFFER_DATA(buf); + sdlsink->yuv[1] = sdlsink->yuv[0] + sdlsink->width*sdlsink->height; + sdlsink->yuv[2] = sdlsink->yuv[1] + sdlsink->width*sdlsink->height/4; + + /* let's draw the data (*yuv[3]) on a SDL screen (*buffer) */ + sdlsink->yuv_overlay->pixels = sdlsink->yuv; + + /* Unlock SDL_yuv_overlay */ + SDL_UnlockYUVOverlay(sdlsink->yuv_overlay); + SDL_UnlockSurface(sdlsink->screen); + + /* Show, baby, show! */ + SDL_DisplayYUVOverlay(sdlsink->yuv_overlay, &(sdlsink->rect)); + SDL_UpdateRect(sdlsink->screen, 0, 0, sdlsink->width, sdlsink->height); + + gtk_signal_emit(GTK_OBJECT(sdlsink),gst_sdlsink_signals[SIGNAL_FRAME_DISPLAYED]); + + gst_buffer_unref(buf); + } + + + static void + gst_sdlsink_set_arg (GtkObject *object, GtkArg *arg, guint id) + { + GstSDLSink *sdlsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_SDLSINK (object)); + + sdlsink = GST_SDLSINK (object); + } + + static void + gst_sdlsink_get_arg (GtkObject *object, GtkArg *arg, guint id) + { + GstSDLSink *sdlsink; + + /* it's not null if we got it, but it might not be ours */ + sdlsink = GST_SDLSINK(object); + + switch(id) { + case ARG_FRAMES_DISPLAYED: { + GTK_VALUE_INT(*arg) = sdlsink->frames_displayed; + break; + } + case ARG_FRAME_TIME: { + GTK_VALUE_INT(*arg) = sdlsink->frame_time/1000000; + break; + } + default: { + arg->type = GTK_TYPE_INVALID; + break; + } + } + } + + static gboolean + gst_sdlsink_open (GstSDLSink *sdlsink) + { + g_return_val_if_fail (!GST_FLAG_IS_SET (sdlsink ,GST_SDLSINK_OPEN), FALSE); + + /* Initialize the SDL library */ + if( SDL_Init(SDL_INIT_VIDEO) < 0 ) { + GST_ERROR(0, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return FALSE; + } + GST_FLAG_SET (sdlsink, GST_SDLSINK_OPEN); + + return TRUE; + } + + static void + gst_sdlsink_close (GstSDLSink *sdlsink) + { + g_return_if_fail (GST_FLAG_IS_SET (sdlsink ,GST_SDLSINK_OPEN)); + + SDL_FreeYUVOverlay(sdlsink->yuv_overlay); + SDL_Quit(); + + GST_FLAG_UNSET (sdlsink, GST_SDLSINK_OPEN); + } + + static GstElementStateReturn + gst_sdlsink_change_state (GstElement *element) + { + g_return_val_if_fail (GST_IS_SDLSINK (element), GST_STATE_FAILURE); + + if (GST_STATE_PENDING (element) == GST_STATE_NULL) { + if (GST_FLAG_IS_SET (element, GST_SDLSINK_OPEN)) + gst_sdlsink_close (GST_SDLSINK (element)); + } else { + if (!GST_FLAG_IS_SET (element, GST_SDLSINK_OPEN)) { + if (!gst_sdlsink_open (GST_SDLSINK (element))) + return GST_STATE_FAILURE; + } + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + + return GST_STATE_SUCCESS; + } + + static gboolean + plugin_init (GModule *module, GstPlugin *plugin) + { + GstElementFactory *factory; + + /* create an elementfactory for the sdlsink element */ + factory = gst_elementfactory_new("sdlsink",GST_TYPE_SDLSINK, + &gst_sdlsink_details); + g_return_val_if_fail(factory != NULL, FALSE); + + gst_elementfactory_add_padtemplate (factory, + GST_PADTEMPLATE_GET (sink_template)); + + gst_plugin_add_factory(plugin,factory); + + return TRUE; + } + + GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "sdlsink", + plugin_init + }; *** plugins/sdlsink/sdlsink.h Thu Aug 24 11:00:32 2000 --- plugins/sdlsink/sdlsink.h Wed May 16 11:05:44 2001 *************** *** 0 **** --- 1,87 ---- + /* GStreamer SDL plugin + * Copyright (C) 2001 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + + #ifndef __GST_SDLSINK_H__ + #define __GST_SDLSINK_H__ + + #include + + #include + + #ifdef __cplusplus + extern "C" { + #endif /* __cplusplus */ + + + #define GST_TYPE_SDLSINK \ + (gst_sdlsink_get_type()) + #define GST_SDLSINK(obj) \ + (GTK_CHECK_CAST((obj),GST_TYPE_SDLSINK,GstSDLSink)) + #define GST_SDLSINK_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_SDLSINK,GstSDLSink)) + #define GST_IS_SDLSINK(obj) \ + (GTK_CHECK_TYPE((obj),GST_TYPE_SDLSINK)) + #define GST_IS_SDLSINK_CLASS(obj) \ + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_SDLSINK)) + + typedef enum { + GST_SDLSINK_OPEN = GST_ELEMENT_FLAG_LAST, + + GST_SDLSINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 2, + } GstSDLSinkFlags; + + typedef struct _GstSDLSink GstSDLSink; + typedef struct _GstSDLSinkClass GstSDLSinkClass; + + struct _GstSDLSink { + GstElement element; + + GstPad *sinkpad; + + gulong format; + gint width, height; + + gint frames_displayed; + guint64 frame_time; + + GstClock *clock; + + unsigned char *yuv[3]; + SDL_Surface *screen; + SDL_Overlay *yuv_overlay; + SDL_Rect rect; + }; + + struct _GstSDLSinkClass { + GstElementClass parent_class; + + /* signals */ + void (*frame_displayed) (GstElement *element); + void (*have_size) (GstElement *element, guint width, guint height); + }; + + GtkType gst_sdlsink_get_type(void); + + #ifdef __cplusplus + } + #endif /* __cplusplus */ + + + #endif /* __GST_SDLSINK_H__ */