diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index fcaef015a1..9f08203221 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -881,6 +881,8 @@ static void gst_rtp_jitter_buffer_flush_stop (GstRtpJitterBuffer * jitterbuffer) { GstRtpJitterBufferPrivate *priv; + GstClock *clock; + GstClockTime ts; priv = jitterbuffer->priv; @@ -902,6 +904,18 @@ gst_rtp_jitter_buffer_flush_stop (GstRtpJitterBuffer * jitterbuffer) GST_DEBUG_OBJECT (jitterbuffer, "flush and reset jitterbuffer"); rtp_jitter_buffer_flush (priv->jbuf); rtp_jitter_buffer_reset_skew (priv->jbuf); + /* sync_time for scheduling timeouts needs proper element base_time + * However, following a seek new base_time only trickles down upon PLAYING + * upon which time quite some processing has already passed + * (which also needs correct base time) */ + clock = gst_element_get_clock (GST_ELEMENT_CAST (jitterbuffer)); + if (clock) { + ts = gst_clock_get_time (clock); + GST_DEBUG_OBJECT (jitterbuffer, "new base time %" GST_TIME_FORMAT, + GST_TIME_ARGS (ts)); + gst_object_unref (clock); + gst_element_set_base_time (GST_ELEMENT_CAST (jitterbuffer), ts); + } JBUF_UNLOCK (priv); } @@ -1218,6 +1232,22 @@ parse_failed: } } +/* call with jbuf lock held */ +static void +check_buffering_percent (GstRtpJitterBuffer * jitterbuffer, gint * percent) +{ + GstRtpJitterBufferPrivate *priv = jitterbuffer->priv; + + /* too short a stream, or too close to EOS will never really fill buffer */ + if (*percent != -1 && priv->npt_stop != -1 && + priv->npt_stop - priv->npt_start <= + rtp_jitter_buffer_get_delay (priv->jbuf)) { + GST_DEBUG_OBJECT (jitterbuffer, "short stream; faking full buffer"); + rtp_jitter_buffer_set_buffering (priv->jbuf, FALSE); + *percent = 100; + } +} + static void post_buffering_percent (GstRtpJitterBuffer * jitterbuffer, gint percent) { @@ -1392,6 +1422,8 @@ gst_rtp_jitter_buffer_chain (GstPad * pad, GstBuffer * buffer) GST_DEBUG_OBJECT (jitterbuffer, "Pushed packet #%d, now %d packets, tail: %d", seqnum, rtp_jitter_buffer_num_packets (priv->jbuf), tail); + check_buffering_percent (jitterbuffer, &percent); + finished: JBUF_UNLOCK (priv); @@ -1822,6 +1854,8 @@ push_buffer: /* when we get here we are ready to pop and push the buffer */ outbuf = rtp_jitter_buffer_pop (priv->jbuf, &percent); + check_buffering_percent (jitterbuffer, &percent); + if (G_UNLIKELY (discont || priv->discont)) { /* set DISCONT flag when we missed a packet. We pushed the buffer writable * into the jitterbuffer so we can modify now. */ @@ -1839,17 +1873,25 @@ push_buffer: elapsed = compute_elapsed (jitterbuffer, outbuf); - if (elapsed > priv->last_elapsed) { + if (elapsed > priv->last_elapsed || !priv->last_elapsed) { guint64 left; priv->last_elapsed = elapsed; left = priv->npt_stop - priv->npt_start; + GST_LOG_OBJECT (jitterbuffer, "left %" GST_TIME_FORMAT, + GST_TIME_ARGS (left)); if (elapsed > 0) estimated = gst_util_uint64_scale (out_time, left, elapsed); - else - estimated = -1; + else { + /* if there is almost nothing left, + * we may never advance enough to end up in the above case */ + if (left < GST_SECOND) + estimated = GST_SECOND; + else + estimated = -1; + } GST_LOG_OBJECT (jitterbuffer, "elapsed %" GST_TIME_FORMAT ", estimated %" GST_TIME_FORMAT, GST_TIME_ARGS (elapsed), GST_TIME_ARGS (estimated)); diff --git a/gst/wavparse/gstwavparse.c b/gst/wavparse/gstwavparse.c index 6e56f8ef22..5f8a789c4e 100644 --- a/gst/wavparse/gstwavparse.c +++ b/gst/wavparse/gstwavparse.c @@ -1156,6 +1156,8 @@ gst_waveparse_ignore_chunk (GstWavParse * wav, GstBuffer * buf, guint32 tag, return TRUE; } +#define MAX_BUFFER_SIZE 4096 + static GstFlowReturn gst_wavparse_stream_headers (GstWavParse * wav) { @@ -1578,6 +1580,19 @@ gst_wavparse_stream_headers (GstWavParse * wav) wav->state = GST_WAVPARSE_DATA; + /* determine reasonable max buffer size, + * that is, buffers not too small either size or time wise + * so we do not end up with too many of them */ + /* var abuse */ + upstream_size = 0; + gst_wavparse_time_to_bytepos (wav, 40 * GST_MSECOND, &upstream_size); + wav->max_buf_size = upstream_size; + wav->max_buf_size = MAX (wav->max_buf_size, MAX_BUFFER_SIZE); + if (wav->blockalign > 0) + wav->max_buf_size -= (wav->max_buf_size % wav->blockalign); + + GST_DEBUG_OBJECT (wav, "max buffer size %d", wav->max_buf_size); + return GST_FLOW_OK; /* ERROR */ @@ -1802,8 +1817,6 @@ gst_wavparse_add_src_pad (GstWavParse * wav, GstBuffer * buf) } } -#define MAX_BUFFER_SIZE 4096 - static GstFlowReturn gst_wavparse_stream_data (GstWavParse * wav) { @@ -1826,7 +1839,7 @@ iterate_adapter: * amounts of data regardless of the playback rate */ desired = MIN (gst_guint64_to_gdouble (wav->dataleft), - MAX_BUFFER_SIZE * wav->segment.abs_rate); + wav->max_buf_size * wav->segment.abs_rate); if (desired >= wav->blockalign && wav->blockalign > 0) desired -= (desired % wav->blockalign); diff --git a/gst/wavparse/gstwavparse.h b/gst/wavparse/gstwavparse.h index 29ce814b95..ecac96881e 100644 --- a/gst/wavparse/gstwavparse.h +++ b/gst/wavparse/gstwavparse.h @@ -90,6 +90,7 @@ struct _GstWavParse { gboolean vbr; guint bytes_per_sample; + guint max_buf_size; /* position in data part */ guint64 offset; diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index 49d70428be..851fae6591 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -774,7 +774,9 @@ static const GstV4L2FormatDesc gst_v4l2_formats[] = { /* compressed formats */ {V4L2_PIX_FMT_MJPEG, TRUE}, {V4L2_PIX_FMT_JPEG, TRUE}, +#ifdef V4L2_PIX_FMT_PJPG {V4L2_PIX_FMT_PJPG, TRUE}, +#endif {V4L2_PIX_FMT_DV, TRUE}, {V4L2_PIX_FMT_MPEG, FALSE}, @@ -815,10 +817,16 @@ gst_v4l2_object_get_format_from_fourcc (GstV4l2Object * v4l2object, return fmt; /* special case for jpeg */ if (fmt->pixelformat == V4L2_PIX_FMT_MJPEG || - fmt->pixelformat == V4L2_PIX_FMT_JPEG || - fmt->pixelformat == V4L2_PIX_FMT_PJPG) { - if (fourcc == V4L2_PIX_FMT_JPEG - || fourcc == V4L2_PIX_FMT_MJPEG || fourcc == V4L2_PIX_FMT_PJPG) { + fmt->pixelformat == V4L2_PIX_FMT_JPEG +#ifdef V4L2_PIX_FMT_PJPG + || fmt->pixelformat == V4L2_PIX_FMT_PJPG +#endif + ) { + if (fourcc == V4L2_PIX_FMT_JPEG || fourcc == V4L2_PIX_FMT_MJPEG +#ifdef V4L2_PIX_FMT_PJPG + || fourcc == V4L2_PIX_FMT_PJPG +#endif + ) { return fmt; } } @@ -858,9 +866,11 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt) switch (fourcc) { case V4L2_PIX_FMT_MJPEG: +#ifdef V4L2_PIX_FMT_PJPG case V4L2_PIX_FMT_PJPG: rank = JPEG_BASE_RANK; break; +#endif case V4L2_PIX_FMT_JPEG: rank = JPEG_BASE_RANK + 1; break; @@ -1077,7 +1087,9 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) switch (fourcc) { case V4L2_PIX_FMT_MJPEG: /* Motion-JPEG */ +#ifdef V4L2_PIX_FMT_PJPG case V4L2_PIX_FMT_PJPG: /* Progressive-JPEG */ +#endif case V4L2_PIX_FMT_JPEG: /* JFIF JPEG */ structure = gst_structure_new ("image/jpeg", NULL); break; diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index 4437a80185..50a972516f 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -5,19 +5,15 @@ JACK_DIR= endif if USE_CAIRO_GOBJECT -if HAVE_GTK_X11 CAIRO_DIR=cairo else CAIRO_DIR= endif -else -CAIRO_DIR= -endif SUBDIRS = audiofx equalizer $(JACK_DIR) level pulse \ rtp shapewipe spectrum v4l2 $(CAIRO_DIR) DIST_SUBDIRS = audiofx equalizer jack level pulse \ - rtp shapewipe spectrum v4l2 $(CAIRO_DIR) + rtp shapewipe spectrum v4l2 cairo include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/tests/examples/cairo/Makefile.am b/tests/examples/cairo/Makefile.am index 1c1a92b435..45f546892b 100644 --- a/tests/examples/cairo/Makefile.am +++ b/tests/examples/cairo/Makefile.am @@ -1,12 +1,7 @@ if USE_CAIRO_GOBJECT -if HAVE_GTK_X11 noinst_PROGRAMS = cairo_overlay endif -endif cairo_overlay_SOURCES = cairo_overlay.c -cairo_overlay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ - $(GTK_CFLAGS) $(CAIRO_CFLAGS) -cairo_overlay_LDFLAGS = \ - $(GST_LIBS) -lgstinterfaces-$(GST_MAJORMINOR) -lgstvideo-$(GST_MAJORMINOR) \ - $(GTK_LIBS) $(CAIRO_LIBS) +cairo_overlay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(CAIRO_CFLAGS) +cairo_overlay_LDADD = -lgstvideo-$(GST_MAJORMINOR) $(GST_LIBS) $(CAIRO_LIBS) diff --git a/tests/examples/cairo/cairo_overlay.c b/tests/examples/cairo/cairo_overlay.c index 52c947b1c2..c941b53b2d 100644 --- a/tests/examples/cairo/cairo_overlay.c +++ b/tests/examples/cairo/cairo_overlay.c @@ -19,72 +19,49 @@ /* * Example showing usage of the cairooverlay element - * - * Note: The example program not run on non-X11 platforms because - * it is using the xvimageoverlay element. That part of the code was - * roughly based on gst_x_overlay documentation. */ #include #include -#include #include #include -#include +#include -#include -static gulong video_window_xid = 0; - -static GstBusSyncReply -bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data) +static gboolean +on_message (GstBus * bus, GstMessage * message, gpointer user_data) { - if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) - return GST_BUS_PASS; - if (!gst_structure_has_name (message->structure, "prepare-xwindow-id")) - return GST_BUS_PASS; + GMainLoop *loop = (GMainLoop *) user_data; - if (video_window_xid != 0) { - GstXOverlay *xoverlay; + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR:{ + GError *err = NULL; + gchar *debug; - xoverlay = GST_X_OVERLAY (GST_MESSAGE_SRC (message)); - gst_x_overlay_set_window_handle (xoverlay, video_window_xid); - } else { - g_warning ("Should have obtained video_window_xid by now!"); + gst_message_parse_error (message, &err, &debug); + g_critical ("Got ERROR: %s (%s)", err->message, GST_STR_NULL (debug)); + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_WARNING:{ + GError *err = NULL; + gchar *debug; + + gst_message_parse_warning (message, &err, &debug); + g_warning ("Got WARNING: %s (%s)", err->message, GST_STR_NULL (debug)); + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_EOS: + g_main_loop_quit (loop); + break; + default: + break; } - gst_message_unref (message); - return GST_BUS_DROP; -} - -static void -video_widget_realize_cb (GtkWidget * widget, gpointer data) -{ - video_window_xid = GDK_WINDOW_XID (widget->window); -} - -static GtkWidget * -setup_gtk_window (void) -{ - GtkWidget *video_window; - GtkWidget *app_window; - - app_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - video_window = gtk_drawing_area_new (); - g_signal_connect (video_window, "realize", - G_CALLBACK (video_widget_realize_cb), NULL); - gtk_widget_set_double_buffered (video_window, FALSE); - - gtk_container_add (GTK_CONTAINER (app_window), video_window); - gtk_widget_show_all (app_window); - - gtk_widget_realize (app_window); - g_assert (video_window_xid != 0); - - return app_window; + return TRUE; } /* Datastructure to share the state we are interested in between @@ -137,7 +114,6 @@ setup_gst_pipeline (CairoOverlayState * overlay_state) GstElement *pipeline; GstElement *cairo_overlay; GstElement *source, *adaptor1, *adaptor2, *sink; - GstBus *bus; pipeline = gst_pipeline_new ("cairo-overlay-example"); @@ -146,7 +122,7 @@ setup_gst_pipeline (CairoOverlayState * overlay_state) adaptor1 = gst_element_factory_make ("ffmpegcolorspace", "adaptor1"); cairo_overlay = gst_element_factory_make ("cairooverlay", "overlay"); adaptor2 = gst_element_factory_make ("ffmpegcolorspace", "adaptor2"); - sink = gst_element_factory_make ("xvimagesink", "sink"); + sink = gst_element_factory_make ("autovideosink", "sink"); /* If failing, the element could not be created */ g_assert (cairo_overlay); @@ -165,31 +141,30 @@ setup_gst_pipeline (CairoOverlayState * overlay_state) g_warning ("Failed to link elements!"); } - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, NULL); - gst_object_unref (bus); - return pipeline; } int main (int argc, char **argv) { - GtkWidget *window; + GMainLoop *loop; GstElement *pipeline; - CairoOverlayState *overlay_state; + GstBus *bus; + CairoOverlayState overlay_state = { FALSE, 0, 0 }; - gtk_init (&argc, &argv); gst_init (&argc, &argv); + loop = g_main_loop_new (NULL, FALSE); - window = setup_gtk_window (); - overlay_state = g_new0 (CairoOverlayState, 1); - pipeline = setup_gst_pipeline (overlay_state); + pipeline = setup_gst_pipeline (&overlay_state); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_signal_watch (bus); + g_signal_connect (G_OBJECT (bus), "message", G_CALLBACK (on_message), loop); + gst_object_unref (GST_OBJECT (bus)); gst_element_set_state (pipeline, GST_STATE_PLAYING); - gtk_main (); + g_main_loop_run (loop); + gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); - gtk_widget_destroy (GTK_WIDGET (window)); - g_free (overlay_state); }