From 08bce008b0a38d5994f926f2a1e61be4541e444d Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 13 Jan 2012 10:25:22 +0000 Subject: [PATCH 01/57] rsvgoverlay: fix adapter leak --- ext/rsvg/gstrsvgoverlay.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ext/rsvg/gstrsvgoverlay.c b/ext/rsvg/gstrsvgoverlay.c index 121d4d252b..42de199f75 100644 --- a/ext/rsvg/gstrsvgoverlay.c +++ b/ext/rsvg/gstrsvgoverlay.c @@ -123,6 +123,8 @@ static GstStaticPadTemplate data_sink_template = GST_BOILERPLATE (GstRsvgOverlay, gst_rsvg_overlay, GstVideoFilter, GST_TYPE_VIDEO_FILTER); +static void gst_rsvg_overlay_finalize (GObject * object); + static void gst_rsvg_overlay_set_svg_data (GstRsvgOverlay * overlay, const gchar * data, gboolean consider_as_filename) @@ -466,6 +468,7 @@ gst_rsvg_overlay_class_init (GstRsvgOverlayClass * klass) gobject_class->set_property = gst_rsvg_overlay_set_property; gobject_class->get_property = gst_rsvg_overlay_get_property; + gobject_class->finalize = gst_rsvg_overlay_finalize; g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DATA, g_param_spec_string ("data", "data", "SVG data.", "", @@ -541,3 +544,13 @@ gst_rsvg_overlay_init (GstRsvgOverlay * overlay, GstRsvgOverlayClass * klass) GST_DEBUG_FUNCPTR (gst_rsvg_overlay_data_sink_event)); gst_element_add_pad (GST_ELEMENT (overlay), overlay->data_sinkpad); } + +static void +gst_rsvg_overlay_finalize (GObject * object) +{ + GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (object); + + g_object_unref (overlay->adapter); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} From 525a995569f318609f23e36a37115e6be8f848f9 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 13 Jan 2012 10:32:59 +0000 Subject: [PATCH 02/57] linsyssdi: fix leaks --- sys/linsys/gstlinsyssdisink.c | 5 +++++ sys/linsys/gstlinsyssdisrc.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sys/linsys/gstlinsyssdisink.c b/sys/linsys/gstlinsyssdisink.c index e4260c0236..28b64b2f93 100644 --- a/sys/linsys/gstlinsyssdisink.c +++ b/sys/linsys/gstlinsyssdisink.c @@ -196,9 +196,14 @@ gst_linsys_sdi_sink_get_property (GObject * object, guint property_id, void gst_linsys_sdi_sink_dispose (GObject * object) { + GstLinsysSdiSink *linsyssdisink; + g_return_if_fail (GST_IS_LINSYS_SDI_SINK (object)); + linsyssdisink = GST_LINSYS_SDI_SINK (object); /* clean up as possible. may be called multiple times */ + g_free (linsyssdisink->device); + linsyssdisink->device = NULL; G_OBJECT_CLASS (parent_class)->dispose (object); } diff --git a/sys/linsys/gstlinsyssdisrc.c b/sys/linsys/gstlinsyssdisrc.c index 467c54c50b..a9732f51ec 100644 --- a/sys/linsys/gstlinsyssdisrc.c +++ b/sys/linsys/gstlinsyssdisrc.c @@ -212,9 +212,12 @@ gst_linsys_sdi_src_get_property (GObject * object, guint property_id, void gst_linsys_sdi_src_dispose (GObject * object) { - g_return_if_fail (GST_IS_LINSYS_SDI_SRC (object)); + GstLinsysSdiSrc *linsyssdisrc = GST_LINSYS_SDI_SRC (object); + g_return_if_fail (linsyssdisrc != NULL); /* clean up as possible. may be called multiple times */ + g_free (linsyssdisrc->device); + linsyssdisrc->device = NULL; G_OBJECT_CLASS (parent_class)->dispose (object); } From 2f78acb42a1527768c6f4114ed3064c1e640c6b7 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 13 Jan 2012 11:22:21 +0000 Subject: [PATCH 03/57] cogmse: fix possible buffer leak --- ext/cog/gstcogmse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/cog/gstcogmse.c b/ext/cog/gstcogmse.c index 8a17e8fe8a..6b6ecf8d65 100644 --- a/ext/cog/gstcogmse.c +++ b/ext/cog/gstcogmse.c @@ -208,6 +208,7 @@ gst_mse_finalize (GObject * object) gst_object_unref (fs->sinkpad_test); g_mutex_free (fs->lock); g_cond_free (fs->cond); + gst_buffer_replace (&fs->buffer_ref, NULL); } static GstCaps * From 23388f2e646814001b97346a6bcf2c14f9ee2e56 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 13 Jan 2012 11:22:42 +0000 Subject: [PATCH 04/57] cogmse: fix typo using the wrong pad --- ext/cog/gstcogmse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/cog/gstcogmse.c b/ext/cog/gstcogmse.c index 6b6ecf8d65..edfd91406a 100644 --- a/ext/cog/gstcogmse.c +++ b/ext/cog/gstcogmse.c @@ -244,7 +244,7 @@ gst_mse_getcaps (GstPad * pad) } if (pad != fs->sinkpad_test) { - peercaps = gst_pad_peer_get_caps (fs->sinkpad_ref); + peercaps = gst_pad_peer_get_caps (fs->sinkpad_test); if (peercaps) { icaps = gst_caps_intersect (caps, peercaps); gst_caps_unref (caps); From 6cad606ead976259d7a45051c289206cafe63bc0 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 13 Jan 2012 12:08:28 +0000 Subject: [PATCH 05/57] sirenenc: fix base class call mixup in finalize --- gst/siren/gstsirenenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/siren/gstsirenenc.c b/gst/siren/gstsirenenc.c index b201e18b20..dbf0f688d4 100644 --- a/gst/siren/gstsirenenc.c +++ b/gst/siren/gstsirenenc.c @@ -156,7 +156,7 @@ gst_siren_enc_finalize (GObject * object) Siren7_CloseEncoder (enc->encoder); g_object_unref (enc->adapter); - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (parent_class)->finalize (object); } static gboolean From 15f41b6887cff3f1662a0c844058b907f5ab90ba Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 13 Jan 2012 12:55:39 +0000 Subject: [PATCH 06/57] cogmse: signal chain functions to exit on flush-start --- ext/cog/gstcogmse.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/cog/gstcogmse.c b/ext/cog/gstcogmse.c index edfd91406a..446d9947dd 100644 --- a/ext/cog/gstcogmse.c +++ b/ext/cog/gstcogmse.c @@ -311,6 +311,7 @@ gst_mse_reset (GstMSE * fs) fs->luma_mse_sum = 0; fs->chroma_mse_sum = 0; fs->n_frames = 0; + fs->cancel = FALSE; if (fs->buffer_ref) { gst_buffer_unref (fs->buffer_ref); @@ -436,9 +437,11 @@ gst_mse_sink_event (GstPad * pad, GstEvent * event) break; case GST_EVENT_FLUSH_START: GST_DEBUG ("flush start"); + fs->cancel = TRUE; break; case GST_EVENT_FLUSH_STOP: GST_DEBUG ("flush stop"); + fs->cancel = FALSE; break; default: break; From 60a0741e16d3f88eef0deae116a50bb58427643b Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 13 Jan 2012 13:30:57 +0000 Subject: [PATCH 07/57] cogmse: fix finalize not calling base class (and leaking) --- ext/cog/gstcogmse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/cog/gstcogmse.c b/ext/cog/gstcogmse.c index 446d9947dd..f85c873c8b 100644 --- a/ext/cog/gstcogmse.c +++ b/ext/cog/gstcogmse.c @@ -209,6 +209,8 @@ gst_mse_finalize (GObject * object) g_mutex_free (fs->lock); g_cond_free (fs->cond); gst_buffer_replace (&fs->buffer_ref, NULL); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } static GstCaps * From 26a1ca09aa7131879bae33a4a9533511d6ad6a79 Mon Sep 17 00:00:00 2001 From: "Reynaldo H. Verdejo Pinochet" Date: Fri, 13 Jan 2012 15:57:33 -0300 Subject: [PATCH 08/57] Android, Fix wrong dinamic linking attempt gstcodecparsers is built as an static library. This change fixes building with the Android buildsystem. --- gst/videoparsers/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index fb54973687..49baeacd1e 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -33,6 +33,7 @@ Android.mk: Makefile.am $(BUILT_SOURCES) $(libgstvideoparsersbad_la_LIBADD) \ -ldl \ -:LIBFILTER_STATIC gstbaseparse-@GST_MAJORMINOR@ \ + gstcodecparsers-@GST_MAJORMINOR@ \ -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ > $@ From 83878ec6ef644c6c50e4389701594fa2449d0d6b Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 16 Jan 2012 16:59:57 +0000 Subject: [PATCH 09/57] spc: fix missing dispose chaining to parent class Not even compiled, I do not have the dependencies needed. --- ext/spc/gstspc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/spc/gstspc.c b/ext/spc/gstspc.c index 70d2340ad4..fb85ca3efd 100644 --- a/ext/spc/gstspc.c +++ b/ext/spc/gstspc.c @@ -167,6 +167,8 @@ gst_spc_dec_dispose (GObject * object) } spc_tag_free (&spc->tag_info); + + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } static GstFlowReturn From 98d10913de15b45429458cc91422606696062408 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 16 Jan 2012 17:01:18 +0000 Subject: [PATCH 10/57] gme: fix missing dispose chaining to parent class Not compiled, I do not have the necessary dependencies. --- ext/gme/gstgme.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/gme/gstgme.c b/ext/gme/gstgme.c index 14ee7d3058..5bfe361daf 100644 --- a/ext/gme/gstgme.c +++ b/ext/gme/gstgme.c @@ -172,6 +172,8 @@ gst_gme_dec_dispose (GObject * object) g_object_unref (gme->adapter); gme->adapter = NULL; } + + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } static GstFlowReturn From 1dfbb14be51f60eafe8e9fc8abf7ac2fd3ea1c2d Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 16 Jan 2012 17:02:22 +0000 Subject: [PATCH 11/57] opencv: fix missing finalize chaining to parent class Not compiled, I do not have the necessary dependencies. --- ext/opencv/gsttemplatematch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/opencv/gsttemplatematch.c b/ext/opencv/gsttemplatematch.c index 569978270c..6568a8bb7e 100644 --- a/ext/opencv/gsttemplatematch.c +++ b/ext/opencv/gsttemplatematch.c @@ -294,6 +294,8 @@ gst_template_match_finalize (GObject * object) if (filter->cvTemplateImage) { cvReleaseImage (&filter->cvTemplateImage); } + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } /* chain function From 31cb57fbb7934f024c93c57b21b58b6b901cfe13 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 16 Jan 2012 17:07:29 +0000 Subject: [PATCH 12/57] mpegdemux: fix missing finalize chaining to parent This code does not seem to trigger on my test streams, so it's a bit of a blind fix, but seems safe enough to push. --- gst/mpegdemux/flutspmtstreaminfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/mpegdemux/flutspmtstreaminfo.c b/gst/mpegdemux/flutspmtstreaminfo.c index 9fd449c834..7ab5ba43c8 100644 --- a/gst/mpegdemux/flutspmtstreaminfo.c +++ b/gst/mpegdemux/flutspmtstreaminfo.c @@ -122,6 +122,8 @@ mpegts_pmt_stream_info_finalize (GObject * object) g_value_array_free (info->languages); g_value_array_free (info->descriptors); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } MpegTsPmtStreamInfo * From 6b4038fed3ec6e6f2a5d6c4d19a2704c901bcbc4 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 16 Jan 2012 17:30:22 +0000 Subject: [PATCH 13/57] debugspy: fix string leak --- gst/debugutils/gstdebugspy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/debugutils/gstdebugspy.c b/gst/debugutils/gstdebugspy.c index 72387ce416..0823f6c430 100644 --- a/gst/debugutils/gstdebugspy.c +++ b/gst/debugutils/gstdebugspy.c @@ -225,6 +225,8 @@ gst_debug_spy_transform_ip (GstBaseTransform * transform, GstBuffer * buf) "size", G_TYPE_UINT, GST_BUFFER_SIZE (buf), "caps", GST_TYPE_CAPS, GST_BUFFER_CAPS (buf), NULL); + g_free (checksum); + message = gst_message_new_element (GST_OBJECT (transform), message_structure); From 0acfa3cc1e6b5e3f6bc40ad8637df20f1b8f65d7 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 17 Jan 2012 18:32:23 +0100 Subject: [PATCH 14/57] gsmenc: port to audioencoder --- ext/gsm/gstgsmenc.c | 174 ++++++++++++++++++-------------------------- ext/gsm/gstgsmenc.h | 12 +-- 2 files changed, 74 insertions(+), 112 deletions(-) diff --git a/ext/gsm/gstgsmenc.c b/ext/gsm/gstgsmenc.c index 52d0b55b22..ea8c43c288 100644 --- a/ext/gsm/gstgsmenc.c +++ b/ext/gsm/gstgsmenc.c @@ -43,39 +43,12 @@ enum ARG_0 }; -static void gst_gsmenc_base_init (gpointer g_class); -static void gst_gsmenc_class_init (GstGSMEnc * klass); -static void gst_gsmenc_init (GstGSMEnc * gsmenc); -static void gst_gsmenc_finalize (GObject * object); - -static gboolean gst_gsmenc_setcaps (GstPad * pad, GstCaps * caps); -static GstFlowReturn gst_gsmenc_chain (GstPad * pad, GstBuffer * buf); - -static GstElementClass *parent_class = NULL; - -GType -gst_gsmenc_get_type (void) -{ - static GType gsmenc_type = 0; - - if (!gsmenc_type) { - static const GTypeInfo gsmenc_info = { - sizeof (GstGSMEncClass), - gst_gsmenc_base_init, - NULL, - (GClassInitFunc) gst_gsmenc_class_init, - NULL, - NULL, - sizeof (GstGSMEnc), - 0, - (GInstanceInitFunc) gst_gsmenc_init, - }; - - gsmenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstGSMEnc", &gsmenc_info, 0); - } - return gsmenc_type; -} +static gboolean gst_gsmenc_start (GstAudioEncoder * enc); +static gboolean gst_gsmenc_stop (GstAudioEncoder * enc); +static gboolean gst_gsmenc_set_format (GstAudioEncoder * enc, + GstAudioInfo * info); +static GstFlowReturn gst_gsmenc_handle_frame (GstAudioEncoder * enc, + GstBuffer * in_buf); static GstStaticPadTemplate gsmenc_src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -95,6 +68,9 @@ GST_STATIC_PAD_TEMPLATE ("sink", "depth = (int) 16, " "rate = (int) 8000, " "channels = (int) 1") ); +GST_BOILERPLATE (GstGSMEnc, gst_gsmenc, GstAudioEncoder, + GST_TYPE_AUDIO_ENCODER); + static void gst_gsmenc_base_init (gpointer g_class) { @@ -110,34 +86,32 @@ gst_gsmenc_base_init (gpointer g_class) } static void -gst_gsmenc_class_init (GstGSMEnc * klass) +gst_gsmenc_class_init (GstGSMEncClass * klass) { - GObjectClass *gobject_class; + GstAudioEncoderClass *base_class; - gobject_class = (GObjectClass *) klass; + base_class = (GstAudioEncoderClass *) klass; - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_gsmenc_finalize; + base_class->start = GST_DEBUG_FUNCPTR (gst_gsmenc_start); + base_class->stop = GST_DEBUG_FUNCPTR (gst_gsmenc_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (gst_gsmenc_set_format); + base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_gsmenc_handle_frame); GST_DEBUG_CATEGORY_INIT (gsmenc_debug, "gsmenc", 0, "GSM Encoder"); } static void -gst_gsmenc_init (GstGSMEnc * gsmenc) +gst_gsmenc_init (GstGSMEnc * gsmenc, GstGSMEncClass * klass) { +} + +static gboolean +gst_gsmenc_start (GstAudioEncoder * enc) +{ + GstGSMEnc *gsmenc = GST_GSMENC (enc); gint use_wav49; - /* create the sink and src pads */ - gsmenc->sinkpad = - gst_pad_new_from_static_template (&gsmenc_sink_template, "sink"); - gst_pad_set_chain_function (gsmenc->sinkpad, gst_gsmenc_chain); - gst_pad_set_setcaps_function (gsmenc->sinkpad, gst_gsmenc_setcaps); - gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->sinkpad); - - gsmenc->srcpad = - gst_pad_new_from_static_template (&gsmenc_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->srcpad); + GST_DEBUG_OBJECT (enc, "start"); gsmenc->state = gsm_create (); @@ -145,78 +119,72 @@ gst_gsmenc_init (GstGSMEnc * gsmenc) use_wav49 = 0; gsm_option (gsmenc->state, GSM_OPT_WAV49, &use_wav49); - gsmenc->adapter = gst_adapter_new (); - gsmenc->next_ts = 0; -} - -static void -gst_gsmenc_finalize (GObject * object) -{ - GstGSMEnc *gsmenc; - - gsmenc = GST_GSMENC (object); - - g_object_unref (gsmenc->adapter); - gsm_destroy (gsmenc->state); - - G_OBJECT_CLASS (parent_class)->finalize (object); + return TRUE; } static gboolean -gst_gsmenc_setcaps (GstPad * pad, GstCaps * caps) +gst_gsmenc_stop (GstAudioEncoder * enc) { - GstGSMEnc *gsmenc; - GstCaps *srccaps; + GstGSMEnc *gsmenc = GST_GSMENC (enc); - gsmenc = GST_GSMENC (gst_pad_get_parent (pad)); - - srccaps = gst_static_pad_template_get_caps (&gsmenc_src_template); - - gst_pad_set_caps (gsmenc->srcpad, srccaps); - - gst_object_unref (gsmenc); + GST_DEBUG_OBJECT (enc, "stop"); + gsm_destroy (gsmenc->state); return TRUE; } +static gboolean +gst_gsmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) +{ + GstGSMEnc *gsmenc; + GstCaps *srccaps; + + gsmenc = GST_GSMENC (benc); + + srccaps = gst_static_pad_template_get_caps (&gsmenc_src_template); + gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (benc), srccaps); + + /* report needs to base class */ + gst_audio_encoder_set_frame_samples_min (benc, 160); + gst_audio_encoder_set_frame_samples_max (benc, 160); + gst_audio_encoder_set_frame_max (benc, 1); + + return TRUE; +} static GstFlowReturn -gst_gsmenc_chain (GstPad * pad, GstBuffer * buf) +gst_gsmenc_handle_frame (GstAudioEncoder * benc, GstBuffer * buffer) { GstGSMEnc *gsmenc; gsm_signal *data; GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *outbuf; - gsmenc = GST_GSMENC (gst_pad_get_parent (pad)); + gsmenc = GST_GSMENC (benc); - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) { - gst_adapter_clear (gsmenc->adapter); - } - gst_adapter_push (gsmenc->adapter, buf); - - while (gst_adapter_available (gsmenc->adapter) >= 320) { - GstBuffer *outbuf; - - outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); - - GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts; - GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND; - gsmenc->next_ts += 20 * GST_MSECOND; - - /* encode 160 16-bit samples into 33 bytes */ - data = (gsm_signal *) gst_adapter_peek (gsmenc->adapter, 320); - gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf)); - gst_adapter_flush (gsmenc->adapter, 320); - - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmenc->srcpad)); - - GST_DEBUG_OBJECT (gsmenc, "Pushing buffer of size %d", - GST_BUFFER_SIZE (outbuf)); - - ret = gst_pad_push (gsmenc->srcpad, outbuf); + /* we don't deal with squeezing remnants, so simply discard those */ + if (G_UNLIKELY (buffer == NULL)) { + GST_DEBUG_OBJECT (gsmenc, "no data"); + goto done; } - gst_object_unref (gsmenc); + if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 320)) { + GST_DEBUG_OBJECT (gsmenc, "discarding trailing data %d", + GST_BUFFER_SIZE (buffer)); + ret = gst_audio_encoder_finish_frame (benc, NULL, -1); + goto done; + } + outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); + + /* encode 160 16-bit samples into 33 bytes */ + data = (gsm_signal *) GST_BUFFER_DATA (buffer); + gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf)); + + GST_LOG_OBJECT (gsmenc, "encoded to %d bytes", GST_BUFFER_SIZE (outbuf)); + + ret = gst_audio_encoder_finish_frame (benc, outbuf, 160); + +done: return ret; } diff --git a/ext/gsm/gstgsmenc.h b/ext/gsm/gstgsmenc.h index ba3b089b7a..28b8e2e297 100644 --- a/ext/gsm/gstgsmenc.h +++ b/ext/gsm/gstgsmenc.h @@ -21,7 +21,7 @@ #define __GST_GSMENC_H__ #include -#include +#include #ifdef GSM_HEADER_IN_SUBDIR #include @@ -47,20 +47,14 @@ typedef struct _GstGSMEncClass GstGSMEncClass; struct _GstGSMEnc { - GstElement element; - - /* pads */ - GstPad *sinkpad, *srcpad; - GstAdapter *adapter; + GstAudioEncoder element; gsm state; - GstClockTime next_ts; - gboolean firstBuf; }; struct _GstGSMEncClass { - GstElementClass parent_class; + GstAudioEncoderClass parent_class; }; GType gst_gsmenc_get_type (void); From bc1c77395e659d7f4e0e051e49f6492bb4974395 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 17 Jan 2012 18:33:09 +0100 Subject: [PATCH 15/57] gsmdec: port to audiodecoder --- ext/gsm/gstgsmdec.c | 267 +++++++++++++++----------------------------- ext/gsm/gstgsmdec.h | 20 +--- 2 files changed, 92 insertions(+), 195 deletions(-) diff --git a/ext/gsm/gstgsmdec.c b/ext/gsm/gstgsmdec.c index 65d3275e55..b9c019d30d 100644 --- a/ext/gsm/gstgsmdec.c +++ b/ext/gsm/gstgsmdec.c @@ -43,43 +43,16 @@ enum ARG_0 }; -static void gst_gsmdec_base_init (gpointer g_class); -static void gst_gsmdec_class_init (GstGSMDec * klass); -static void gst_gsmdec_init (GstGSMDec * gsmdec); -static void gst_gsmdec_finalize (GObject * object); - -static gboolean gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps); -static gboolean gst_gsmdec_sink_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_gsmdec_chain (GstPad * pad, GstBuffer * buf); - -static GstElementClass *parent_class = NULL; +static gboolean gst_gsmdec_start (GstAudioDecoder * dec); +static gboolean gst_gsmdec_stop (GstAudioDecoder * dec); +static gboolean gst_gsmdec_set_format (GstAudioDecoder * dec, GstCaps * caps); +static GstFlowReturn gst_gsmdec_parse (GstAudioDecoder * dec, + GstAdapter * adapter, gint * offset, gint * length); +static GstFlowReturn gst_gsmdec_handle_frame (GstAudioDecoder * dec, + GstBuffer * in_buf); /*static guint gst_gsmdec_signals[LAST_SIGNAL] = { 0 }; */ -GType -gst_gsmdec_get_type (void) -{ - static GType gsmdec_type = 0; - - if (!gsmdec_type) { - static const GTypeInfo gsmdec_info = { - sizeof (GstGSMDecClass), - gst_gsmdec_base_init, - NULL, - (GClassInitFunc) gst_gsmdec_class_init, - NULL, - NULL, - sizeof (GstGSMDec), - 0, - (GInstanceInitFunc) gst_gsmdec_init, - }; - - gsmdec_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstGSMDec", &gsmdec_info, 0); - } - return gsmdec_type; -} - #define ENCODED_SAMPLES 160 static GstStaticPadTemplate gsmdec_sink_template = @@ -101,6 +74,9 @@ GST_STATIC_PAD_TEMPLATE ("src", "depth = (int) 16, " "rate = (int) [1, MAX], " "channels = (int) 1") ); +GST_BOILERPLATE (GstGSMDec, gst_gsmdec, GstAudioDecoder, + GST_TYPE_AUDIO_DECODER); + static void gst_gsmdec_base_init (gpointer g_class) { @@ -116,63 +92,60 @@ gst_gsmdec_base_init (gpointer g_class) } static void -gst_gsmdec_class_init (GstGSMDec * klass) +gst_gsmdec_class_init (GstGSMDecClass * klass) { - GObjectClass *gobject_class; + GstAudioDecoderClass *base_class; - gobject_class = (GObjectClass *) klass; + base_class = (GstAudioDecoderClass *) klass; - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_gsmdec_finalize; + base_class->start = GST_DEBUG_FUNCPTR (gst_gsmdec_start); + base_class->stop = GST_DEBUG_FUNCPTR (gst_gsmdec_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (gst_gsmdec_set_format); + base_class->parse = GST_DEBUG_FUNCPTR (gst_gsmdec_parse); + base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_gsmdec_handle_frame); GST_DEBUG_CATEGORY_INIT (gsmdec_debug, "gsmdec", 0, "GSM Decoder"); } static void -gst_gsmdec_init (GstGSMDec * gsmdec) +gst_gsmdec_init (GstGSMDec * gsmdec, GstGSMDecClass * klass) { - /* create the sink and src pads */ - gsmdec->sinkpad = - gst_pad_new_from_static_template (&gsmdec_sink_template, "sink"); - gst_pad_set_setcaps_function (gsmdec->sinkpad, gst_gsmdec_sink_setcaps); - gst_pad_set_event_function (gsmdec->sinkpad, gst_gsmdec_sink_event); - gst_pad_set_chain_function (gsmdec->sinkpad, gst_gsmdec_chain); - gst_element_add_pad (GST_ELEMENT (gsmdec), gsmdec->sinkpad); - - gsmdec->srcpad = - gst_pad_new_from_static_template (&gsmdec_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (gsmdec), gsmdec->srcpad); - - gsmdec->state = gsm_create (); - - gsmdec->adapter = gst_adapter_new (); - gsmdec->next_of = 0; - gsmdec->next_ts = 0; -} - -static void -gst_gsmdec_finalize (GObject * object) -{ - GstGSMDec *gsmdec; - - gsmdec = GST_GSMDEC (object); - - g_object_unref (gsmdec->adapter); - gsm_destroy (gsmdec->state); - - G_OBJECT_CLASS (parent_class)->finalize (object); } static gboolean -gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps) +gst_gsmdec_start (GstAudioDecoder * dec) +{ + GstGSMDec *gsmdec = GST_GSMDEC (dec); + + GST_DEBUG_OBJECT (dec, "start"); + + gsmdec->state = gsm_create (); + + return TRUE; +} + +static gboolean +gst_gsmdec_stop (GstAudioDecoder * dec) +{ + GstGSMDec *gsmdec = GST_GSMDEC (dec); + + GST_DEBUG_OBJECT (dec, "stop"); + + gsm_destroy (gsmdec->state); + + return TRUE; +} + +static gboolean +gst_gsmdec_set_format (GstAudioDecoder * dec, GstCaps * caps) { GstGSMDec *gsmdec; GstCaps *srccaps; GstStructure *s; gboolean ret = FALSE; + gint rate; - gsmdec = GST_GSMDEC (gst_pad_get_parent (pad)); + gsmdec = GST_GSMDEC (dec); s = gst_caps_get_structure (caps, 0); if (s == NULL) @@ -186,7 +159,9 @@ gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps) else goto wrong_caps; - if (!gst_structure_get_int (s, "rate", &gsmdec->rate)) { + gsmdec->needed = 33; + + if (!gst_structure_get_int (s, "rate", &rate)) { GST_WARNING_OBJECT (gsmdec, "missing sample rate parameter from sink caps"); goto beach; } @@ -194,21 +169,16 @@ gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps) /* MSGSM needs different framing */ gsm_option (gsmdec->state, GSM_OPT_WAV49, &gsmdec->use_wav49); - gsmdec->duration = gst_util_uint64_scale (ENCODED_SAMPLES, - GST_SECOND, gsmdec->rate); - /* Setting up src caps based on the input sample rate. */ srccaps = gst_caps_new_simple ("audio/x-raw-int", "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, - "rate", G_TYPE_INT, gsmdec->rate, "channels", G_TYPE_INT, 1, NULL); - - ret = gst_pad_set_caps (gsmdec->srcpad, srccaps); + "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, 1, NULL); + ret = gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), srccaps); gst_caps_unref (srccaps); - gst_object_unref (gsmdec); return ret; @@ -218,127 +188,66 @@ wrong_caps: GST_ERROR_OBJECT (gsmdec, "invalid caps received"); beach: - gst_object_unref (gsmdec); return ret; } -static gboolean -gst_gsmdec_sink_event (GstPad * pad, GstEvent * event) +static GstFlowReturn +gst_gsmdec_parse (GstAudioDecoder * dec, GstAdapter * adapter, + gint * offset, gint * length) { - gboolean res; - GstGSMDec *gsmdec; + GstGSMDec *gsmdec = GST_GSMDEC (dec); + guint size; - gsmdec = GST_GSMDEC (gst_pad_get_parent (pad)); + size = gst_adapter_available (adapter); + g_return_val_if_fail (size > 0, GST_FLOW_ERROR); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_START: - res = gst_pad_push_event (gsmdec->srcpad, event); - break; - case GST_EVENT_FLUSH_STOP: - gst_segment_init (&gsmdec->segment, GST_FORMAT_UNDEFINED); - res = gst_pad_push_event (gsmdec->srcpad, event); - break; - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - /* now configure the values */ - gst_segment_set_newsegment_full (&gsmdec->segment, update, - rate, arate, format, start, stop, time); - - /* and forward */ - res = gst_pad_push_event (gsmdec->srcpad, event); - break; - } - case GST_EVENT_EOS: - default: - res = gst_pad_push_event (gsmdec->srcpad, event); - break; + /* WAV49 requires alternating 33 and 32 bytes of input */ + if (gsmdec->use_wav49) { + gsmdec->needed = (gsmdec->needed == 33 ? 32 : 33); } - gst_object_unref (gsmdec); + if (size < gsmdec->needed) + return GST_FLOW_UNEXPECTED; - return res; + *offset = 0; + *length = gsmdec->needed; + + return GST_FLOW_OK; } static GstFlowReturn -gst_gsmdec_chain (GstPad * pad, GstBuffer * buf) +gst_gsmdec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer) { GstGSMDec *gsmdec; gsm_byte *data; GstFlowReturn ret = GST_FLOW_OK; - GstClockTime timestamp; - gint needed; + GstBuffer *outbuf; - gsmdec = GST_GSMDEC (gst_pad_get_parent (pad)); + /* no fancy draining */ + if (G_UNLIKELY (!buffer)) + return GST_FLOW_OK; - timestamp = GST_BUFFER_TIMESTAMP (buf); + gsmdec = GST_GSMDEC (dec); - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) { - gst_adapter_clear (gsmdec->adapter); - gsmdec->next_ts = GST_CLOCK_TIME_NONE; - /* FIXME, do some good offset */ - gsmdec->next_of = 0; - } - gst_adapter_push (gsmdec->adapter, buf); + /* always the same amount of output samples */ + outbuf = gst_buffer_new_and_alloc (ENCODED_SAMPLES * sizeof (gsm_signal)); - needed = 33; - /* do we have enough bytes to read a frame */ - while (gst_adapter_available (gsmdec->adapter) >= needed) { - GstBuffer *outbuf; - - /* always the same amount of output samples */ - outbuf = gst_buffer_new_and_alloc (ENCODED_SAMPLES * sizeof (gsm_signal)); - - /* If we are not given any timestamp, interpolate from last seen - * timestamp (if any). */ - if (timestamp == GST_CLOCK_TIME_NONE) - timestamp = gsmdec->next_ts; - - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - - /* interpolate in the next run */ - if (timestamp != GST_CLOCK_TIME_NONE) - gsmdec->next_ts = timestamp + gsmdec->duration; - timestamp = GST_CLOCK_TIME_NONE; - - GST_BUFFER_DURATION (outbuf) = gsmdec->duration; - GST_BUFFER_OFFSET (outbuf) = gsmdec->next_of; - if (gsmdec->next_of != -1) - gsmdec->next_of += ENCODED_SAMPLES; - GST_BUFFER_OFFSET_END (outbuf) = gsmdec->next_of; - - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmdec->srcpad)); - - /* now encode frame into the output buffer */ - data = (gsm_byte *) gst_adapter_peek (gsmdec->adapter, needed); - if (gsm_decode (gsmdec->state, data, - (gsm_signal *) GST_BUFFER_DATA (outbuf)) < 0) { - /* invalid frame */ - GST_WARNING_OBJECT (gsmdec, "tried to decode an invalid frame, skipping"); - } - gst_adapter_flush (gsmdec->adapter, needed); - - /* WAV49 requires alternating 33 and 32 bytes of input */ - if (gsmdec->use_wav49) - needed = (needed == 33 ? 32 : 33); - - GST_DEBUG_OBJECT (gsmdec, "Pushing buffer of size %d ts %" GST_TIME_FORMAT, - GST_BUFFER_SIZE (outbuf), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))); - - /* push */ - ret = gst_pad_push (gsmdec->srcpad, outbuf); + /* now encode frame into the output buffer */ + data = (gsm_byte *) GST_BUFFER_DATA (buffer); + if (gsm_decode (gsmdec->state, data, + (gsm_signal *) GST_BUFFER_DATA (outbuf)) < 0) { + /* invalid frame */ + GST_AUDIO_DECODER_ERROR (gsmdec, 1, STREAM, DECODE, (NULL), + ("tried to decode an invalid frame"), ret); + if (ret != GST_FLOW_OK) + goto exit; + gst_buffer_unref (outbuf); + outbuf = NULL; } - gst_object_unref (gsmdec); + gst_audio_decoder_finish_frame (dec, outbuf, 1); +exit: return ret; } diff --git a/ext/gsm/gstgsmdec.h b/ext/gsm/gstgsmdec.h index 0013aa47e5..d3ddec604e 100644 --- a/ext/gsm/gstgsmdec.h +++ b/ext/gsm/gstgsmdec.h @@ -21,7 +21,7 @@ #define __GST_GSMDEC_H__ #include -#include +#include #ifdef GSM_HEADER_IN_SUBDIR #include @@ -47,28 +47,16 @@ typedef struct _GstGSMDecClass GstGSMDecClass; struct _GstGSMDec { - GstElement element; - - /* pads */ - GstPad *sinkpad, *srcpad; + GstAudioDecoder element; gsm state; gint use_wav49; - gint64 next_of; - GstClockTime next_ts; - - GstAdapter *adapter; - - GstSegment segment; - - gint rate; - - GstClockTime duration; + gint needed; }; struct _GstGSMDecClass { - GstElementClass parent_class; + GstAudioDecoderClass parent_class; }; GType gst_gsmdec_get_type (void); From 1a73bf0b7994ce3b84c498d6a6f5d9086eb977f2 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 17 Jan 2012 21:36:08 +0100 Subject: [PATCH 16/57] adpcmenc: port to audioencoder --- gst/adpcmenc/Makefile.am | 5 +- gst/adpcmenc/adpcmenc.c | 215 +++++++++++---------------------------- 2 files changed, 64 insertions(+), 156 deletions(-) diff --git a/gst/adpcmenc/Makefile.am b/gst/adpcmenc/Makefile.am index 17b3ecd280..bfd945d508 100644 --- a/gst/adpcmenc/Makefile.am +++ b/gst/adpcmenc/Makefile.am @@ -5,8 +5,9 @@ libgstadpcmenc_la_SOURCES = adpcmenc.c # flags used to compile this plugin # add other _CFLAGS and _LIBS as needed -libgstadpcmenc_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) -libgstadpcmenc_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) +libgstadpcmenc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstadpcmenc_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-@GST_MAJORMINOR@ \ + $(GST_LIBS) libgstadpcmenc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstadpcmenc_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/gst/adpcmenc/adpcmenc.c b/gst/adpcmenc/adpcmenc.c index d8ce1db490..6f434e30f9 100644 --- a/gst/adpcmenc/adpcmenc.c +++ b/gst/adpcmenc/adpcmenc.c @@ -28,7 +28,7 @@ #endif #include -#include +#include #define GST_TYPE_ADPCM_ENC \ (adpcmenc_get_type ()) @@ -113,17 +113,12 @@ adpcmenc_layout_get_type (void) typedef struct _ADPCMEncClass { - GstElementClass parent_class; + GstAudioEncoderClass parent_class; } ADPCMEncClass; typedef struct _ADPCMEnc { - GstElement parent; - - GstPad *sinkpad; - GstPad *srcpad; - - GstCaps *output_caps; + GstAudioEncoder parent; enum adpcm_layout layout; int rate; @@ -133,19 +128,11 @@ typedef struct _ADPCMEnc guint8 step_index[2]; - gboolean is_setup; - - GstClockTime timestamp; - GstClockTime base_timestamp; - - guint64 out_samples; - - GstAdapter *adapter; - } ADPCMEnc; GType adpcmenc_get_type (void); -GST_BOILERPLATE (ADPCMEnc, adpcmenc, GstElement, GST_TYPE_ELEMENT); +GST_BOILERPLATE (ADPCMEnc, adpcmenc, GstAudioEncoder, GST_TYPE_AUDIO_ENCODER); + static gboolean adpcmenc_setup (ADPCMEnc * enc) { @@ -153,6 +140,7 @@ adpcmenc_setup (ADPCMEnc * enc) const int ADPCM_SAMPLES_PER_BYTE = 2; guint64 sample_bytes; const char *layout; + GstCaps *caps; switch (enc->layout) { case LAYOUT_ADPCM_DVI: @@ -168,21 +156,14 @@ adpcmenc_setup (ADPCMEnc * enc) return FALSE; } - enc->output_caps = gst_caps_new_simple ("audio/x-adpcm", + caps = gst_caps_new_simple ("audio/x-adpcm", "rate", G_TYPE_INT, enc->rate, "channels", G_TYPE_INT, enc->channels, "layout", G_TYPE_STRING, layout, "block_align", G_TYPE_INT, enc->blocksize, NULL); - if (enc->output_caps) { - gst_pad_set_caps (enc->srcpad, enc->output_caps); - } - - enc->is_setup = TRUE; - enc->timestamp = GST_CLOCK_TIME_NONE; - enc->base_timestamp = GST_CLOCK_TIME_NONE; - enc->adapter = gst_adapter_new (); - enc->out_samples = 0; + gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps); + gst_caps_unref (caps); /* Step index state is carried between blocks. */ enc->step_index[0] = 0; @@ -191,37 +172,21 @@ adpcmenc_setup (ADPCMEnc * enc) return TRUE; } -static void -adpcmenc_teardown (ADPCMEnc * enc) -{ - if (enc->output_caps) { - gst_caps_unref (enc->output_caps); - enc->output_caps = NULL; - } - if (enc->adapter) { - g_object_unref (enc->adapter); - enc->adapter = NULL; - } - enc->is_setup = FALSE; -} - static gboolean -adpcmenc_sink_setcaps (GstPad * pad, GstCaps * caps) +adpcmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { - ADPCMEnc *enc = (ADPCMEnc *) gst_pad_get_parent (pad); - GstStructure *structure = gst_caps_get_structure (caps, 0); + ADPCMEnc *enc = (ADPCMEnc *) (benc); - if (!gst_structure_get_int (structure, "rate", &enc->rate)) - return FALSE; - if (!gst_structure_get_int (structure, "channels", &enc->channels)) + enc->rate = GST_AUDIO_INFO_RATE (info); + enc->channels = GST_AUDIO_INFO_CHANNELS (info); + + if (!adpcmenc_setup (enc)) return FALSE; - if (enc->is_setup) { - adpcmenc_teardown (enc); - } - adpcmenc_setup (enc); - - gst_object_unref (enc); + /* report needs to base class */ + gst_audio_encoder_set_frame_samples_min (benc, enc->samples_per_block); + gst_audio_encoder_set_frame_samples_max (benc, enc->samples_per_block); + gst_audio_encoder_set_frame_max (benc, 1); return TRUE; } @@ -368,148 +333,86 @@ adpcmenc_encode_ima_block (ADPCMEnc * enc, const gint16 * samples, return TRUE; } -static GstFlowReturn +static GstBuffer * adpcmenc_encode_block (ADPCMEnc * enc, const gint16 * samples, int blocksize) { - gboolean res; + gboolean res = FALSE; GstBuffer *outbuf = NULL; if (enc->layout == LAYOUT_ADPCM_DVI) { outbuf = gst_buffer_new_and_alloc (enc->blocksize); res = adpcmenc_encode_ima_block (enc, samples, GST_BUFFER_DATA (outbuf)); } else { + /* should not happen afaics */ + g_assert_not_reached (); GST_WARNING_OBJECT (enc, "Unknown layout"); - return GST_FLOW_ERROR; + res = FALSE; } if (!res) { - gst_buffer_unref (outbuf); + if (outbuf) + gst_buffer_unref (outbuf); + outbuf = NULL; GST_WARNING_OBJECT (enc, "Encode of block failed"); - return GST_FLOW_ERROR; } - gst_buffer_set_caps (outbuf, enc->output_caps); - GST_BUFFER_TIMESTAMP (outbuf) = enc->timestamp; - - enc->out_samples += enc->samples_per_block; - enc->timestamp = enc->base_timestamp + - gst_util_uint64_scale_int (enc->out_samples, GST_SECOND, enc->rate); - GST_BUFFER_DURATION (outbuf) = enc->timestamp - GST_BUFFER_TIMESTAMP (outbuf); - - return gst_pad_push (enc->srcpad, outbuf); + return outbuf; } static GstFlowReturn -adpcmenc_chain (GstPad * pad, GstBuffer * buf) +adpcmenc_handle_frame (GstAudioEncoder * benc, GstBuffer * buffer) { - ADPCMEnc *enc = (ADPCMEnc *) gst_pad_get_parent (pad); + ADPCMEnc *enc = (ADPCMEnc *) (benc); GstFlowReturn ret = GST_FLOW_OK; gint16 *samples; - GstBuffer *databuf = NULL; + GstBuffer *outbuf; int input_bytes_per_block; const int BYTES_PER_SAMPLE = 2; - if (enc->base_timestamp == GST_CLOCK_TIME_NONE) { - enc->base_timestamp = GST_BUFFER_TIMESTAMP (buf); - if (enc->base_timestamp == GST_CLOCK_TIME_NONE) - enc->base_timestamp = 0; - enc->timestamp = enc->base_timestamp; + /* we don't deal with squeezing remnants, so simply discard those */ + if (G_UNLIKELY (buffer == NULL)) { + GST_DEBUG_OBJECT (benc, "no data"); + goto done; } - gst_adapter_push (enc->adapter, buf); - input_bytes_per_block = enc->samples_per_block * BYTES_PER_SAMPLE * enc->channels; - while (gst_adapter_available (enc->adapter) >= input_bytes_per_block) { - databuf = gst_adapter_take_buffer (enc->adapter, input_bytes_per_block); - samples = (gint16 *) GST_BUFFER_DATA (databuf); - ret = adpcmenc_encode_block (enc, samples, enc->blocksize); - gst_buffer_unref (databuf); - if (ret != GST_FLOW_OK) - goto done; + if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < input_bytes_per_block)) { + GST_DEBUG_OBJECT (enc, "discarding trailing data %d", + GST_BUFFER_SIZE (buffer)); + ret = gst_audio_encoder_finish_frame (benc, NULL, -1); + goto done; } + samples = (gint16 *) GST_BUFFER_DATA (buffer); + outbuf = adpcmenc_encode_block (enc, samples, enc->blocksize); + + ret = gst_audio_encoder_finish_frame (benc, outbuf, enc->samples_per_block); + done: - gst_object_unref (enc); return ret; } static gboolean -adpcmenc_sink_event (GstPad * pad, GstEvent * event) +adpcmenc_start (GstAudioEncoder * enc) { - ADPCMEnc *enc = (ADPCMEnc *) gst_pad_get_parent (pad); - gboolean res; - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - enc->out_samples = 0; - enc->timestamp = GST_CLOCK_TIME_NONE; - enc->base_timestamp = GST_CLOCK_TIME_NONE; - gst_adapter_clear (enc->adapter); - /* Fall through */ - default: - res = gst_pad_push_event (enc->srcpad, event); - break; - } - gst_object_unref (enc); - return res; + GST_DEBUG_OBJECT (enc, "start"); + + return TRUE; } -static GstStateChangeReturn -adpcmenc_change_state (GstElement * element, GstStateChange transition) +static gboolean +adpcmenc_stop (GstAudioEncoder * enc) { - GstStateChangeReturn ret; - ADPCMEnc *enc = (ADPCMEnc *) element; + GST_DEBUG_OBJECT (enc, "stop"); - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - 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: - adpcmenc_teardown (enc); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - return ret; -} - -static void -adpcmenc_dispose (GObject * obj) -{ - G_OBJECT_CLASS (parent_class)->dispose (obj); + return TRUE; } static void adpcmenc_init (ADPCMEnc * enc, ADPCMEncClass * klass) { - enc->sinkpad = - gst_pad_new_from_static_template (&adpcmenc_sink_template, "sink"); - gst_pad_set_setcaps_function (enc->sinkpad, - GST_DEBUG_FUNCPTR (adpcmenc_sink_setcaps)); - gst_pad_set_chain_function (enc->sinkpad, GST_DEBUG_FUNCPTR (adpcmenc_chain)); - gst_pad_set_event_function (enc->sinkpad, - GST_DEBUG_FUNCPTR (adpcmenc_sink_event)); - gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad); - - enc->srcpad = - gst_pad_new_from_static_template (&adpcmenc_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad); - /* Set defaults. */ enc->blocksize = DEFAULT_ADPCM_BLOCK_SIZE; enc->layout = DEFAULT_ADPCM_LAYOUT; @@ -519,11 +422,16 @@ static void adpcmenc_class_init (ADPCMEncClass * klass) { GObjectClass *gobjectclass = (GObjectClass *) klass; - GstElementClass *gstelement_class = (GstElementClass *) klass; + GstAudioEncoderClass *base_class = (GstAudioEncoderClass *) klass; gobjectclass->set_property = adpcmenc_set_property; gobjectclass->get_property = adpcmenc_get_property; + base_class->start = GST_DEBUG_FUNCPTR (adpcmenc_start); + base_class->stop = GST_DEBUG_FUNCPTR (adpcmenc_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (adpcmenc_set_format); + base_class->handle_frame = GST_DEBUG_FUNCPTR (adpcmenc_handle_frame); + g_object_class_install_property (gobjectclass, ARG_LAYOUT, g_param_spec_enum ("layout", "Layout", "Layout for output stream", @@ -537,10 +445,9 @@ adpcmenc_class_init (ADPCMEncClass * klass) DEFAULT_ADPCM_BLOCK_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gobjectclass->dispose = adpcmenc_dispose; - gstelement_class->change_state = adpcmenc_change_state; -} static void +} +static void adpcmenc_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); From dbc8bbd755b4e4e3440e27e08f107346158c5706 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 17 Jan 2012 21:36:21 +0100 Subject: [PATCH 17/57] adpcmdec: port to audiodecoder --- gst/adpcmdec/Makefile.am | 5 +- gst/adpcmdec/adpcmdec.c | 271 ++++++++++++++------------------------- 2 files changed, 96 insertions(+), 180 deletions(-) diff --git a/gst/adpcmdec/Makefile.am b/gst/adpcmdec/Makefile.am index 2521fe6f1f..84e1252242 100644 --- a/gst/adpcmdec/Makefile.am +++ b/gst/adpcmdec/Makefile.am @@ -5,8 +5,9 @@ libgstadpcmdec_la_SOURCES = adpcmdec.c # flags used to compile this plugin # add other _CFLAGS and _LIBS as needed -libgstadpcmdec_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) -libgstadpcmdec_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) +libgstadpcmdec_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstadpcmdec_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-@GST_MAJORMINOR@ \ + $(GST_LIBS) libgstadpcmdec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstadpcmdec_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/gst/adpcmdec/adpcmdec.c b/gst/adpcmdec/adpcmdec.c index b97584cb9e..4cfccb6cc0 100644 --- a/gst/adpcmdec/adpcmdec.c +++ b/gst/adpcmdec/adpcmdec.c @@ -28,7 +28,7 @@ #endif #include -#include +#include #define GST_TYPE_ADPCM_DEC \ (adpcmdec_get_type ()) @@ -69,80 +69,29 @@ enum adpcm_layout typedef struct _ADPCMDecClass { - GstElementClass parent_class; + GstAudioDecoderClass parent_class; } ADPCMDecClass; typedef struct _ADPCMDec { - GstElement parent; - - GstPad *sinkpad; - GstPad *srcpad; - - GstCaps *output_caps; + GstAudioDecoder parent; enum adpcm_layout layout; int rate; int channels; int blocksize; - - gboolean is_setup; - - GstClockTime timestamp; - GstClockTime base_timestamp; - - guint64 out_samples; - - GstAdapter *adapter; - } ADPCMDec; GType adpcmdec_get_type (void); -GST_BOILERPLATE (ADPCMDec, adpcmdec, GstElement, GST_TYPE_ELEMENT); -static gboolean -adpcmdec_setup (ADPCMDec * dec) -{ - dec->output_caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, dec->rate, - "channels", G_TYPE_INT, dec->channels, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "signed", G_TYPE_BOOLEAN, TRUE, NULL); - - if (dec->output_caps) { - gst_pad_set_caps (dec->srcpad, dec->output_caps); - } - - dec->is_setup = TRUE; - dec->timestamp = GST_CLOCK_TIME_NONE; - dec->base_timestamp = GST_CLOCK_TIME_NONE; - dec->adapter = gst_adapter_new (); - dec->out_samples = 0; - - return TRUE; -} - -static void -adpcmdec_teardown (ADPCMDec * dec) -{ - if (dec->output_caps) { - gst_caps_unref (dec->output_caps); - dec->output_caps = NULL; - } - if (dec->adapter) { - g_object_unref (dec->adapter); - dec->adapter = NULL; - } - dec->is_setup = FALSE; -} +GST_BOILERPLATE (ADPCMDec, adpcmdec, GstAudioDecoder, GST_TYPE_AUDIO_DECODER); static gboolean -adpcmdec_sink_setcaps (GstPad * pad, GstCaps * caps) +adpcmdec_set_format (GstAudioDecoder * bdec, GstCaps * in_caps) { - ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad); - GstStructure *structure = gst_caps_get_structure (caps, 0); + ADPCMDec *dec = (ADPCMDec *) (bdec); + GstStructure *structure = gst_caps_get_structure (in_caps, 0); const gchar *layout; + GstCaps *caps; layout = gst_structure_get_string (structure, "layout"); if (!layout) @@ -163,9 +112,16 @@ adpcmdec_sink_setcaps (GstPad * pad, GstCaps * caps) if (!gst_structure_get_int (structure, "channels", &dec->channels)) return FALSE; - if (dec->is_setup) - adpcmdec_teardown (dec); - gst_object_unref (dec); + caps = gst_caps_new_simple ("audio/x-raw-int", + "rate", G_TYPE_INT, dec->rate, + "channels", G_TYPE_INT, dec->channels, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, G_BYTE_ORDER, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + + gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (bdec), caps); + gst_caps_unref (caps); return TRUE; } @@ -377,10 +333,10 @@ adpcmdec_decode_ima_block (ADPCMDec * dec, int n_samples, const guint8 * data, return TRUE; } -static GstFlowReturn +static GstBuffer * adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize) { - gboolean res; + gboolean res = FALSE; GstBuffer *outbuf = NULL; int outsize; int samples; @@ -390,7 +346,7 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize) give two initial sample values per channel. Then the remainder gives two samples per byte */ if (blocksize < 7 * dec->channels) - return GST_FLOW_ERROR; + goto exit; samples = (blocksize - 7 * dec->channels) * 2 + 2 * dec->channels; outsize = 2 * samples; outbuf = gst_buffer_new_and_alloc (outsize); @@ -401,7 +357,7 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize) /* Each block has a 4 byte header per channel, include an initial sample. Then the remainder gives two samples per byte */ if (blocksize < 4 * dec->channels) - return GST_FLOW_ERROR; + goto exit; samples = (blocksize - 4 * dec->channels) * 2 + dec->channels; outsize = 2 * samples; outbuf = gst_buffer_new_and_alloc (outsize); @@ -410,155 +366,114 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize) (gint16 *) (GST_BUFFER_DATA (outbuf))); } else { GST_WARNING_OBJECT (dec, "Unknown layout"); - return GST_FLOW_ERROR; } if (!res) { - gst_buffer_unref (outbuf); + if (outbuf) + gst_buffer_unref (outbuf); + outbuf = NULL; GST_WARNING_OBJECT (dec, "Decode of block failed"); - return GST_FLOW_ERROR; } - gst_buffer_set_caps (outbuf, dec->output_caps); - GST_BUFFER_TIMESTAMP (outbuf) = dec->timestamp; - dec->out_samples += samples / dec->channels; - dec->timestamp = dec->base_timestamp + - gst_util_uint64_scale_int (dec->out_samples, GST_SECOND, dec->rate); - GST_BUFFER_DURATION (outbuf) = dec->timestamp - GST_BUFFER_TIMESTAMP (outbuf); - - return gst_pad_push (dec->srcpad, outbuf); +exit: + return outbuf; } static GstFlowReturn -adpcmdec_chain (GstPad * pad, GstBuffer * buf) +adpcmdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter, + gint * offset, gint * length) { - ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad); + ADPCMDec *dec = (ADPCMDec *) (bdec); + guint size; + + size = gst_adapter_available (adapter); + g_return_val_if_fail (size > 0, GST_FLOW_ERROR); + + if (dec->blocksize < 0) { + /* No explicit blocksize; we just process one input buffer at a time */ + *offset = 0; + *length = size; + } else { + if (size >= dec->blocksize) { + *offset = 0; + *length = dec->blocksize; + } else { + return GST_FLOW_UNEXPECTED; + } + } + + return GST_FLOW_OK; +} + +static GstFlowReturn +adpcmdec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buffer) +{ + ADPCMDec *dec = (ADPCMDec *) (bdec); GstFlowReturn ret = GST_FLOW_OK; guint8 *data; - GstBuffer *databuf = NULL; + GstBuffer *outbuf = NULL; - if (!dec->is_setup) - adpcmdec_setup (dec); + /* no fancy draining */ + if (G_UNLIKELY (!buffer)) + return GST_FLOW_OK; - if (dec->base_timestamp == GST_CLOCK_TIME_NONE) { - dec->base_timestamp = GST_BUFFER_TIMESTAMP (buf); - if (dec->base_timestamp == GST_CLOCK_TIME_NONE) - dec->base_timestamp = 0; - dec->timestamp = dec->base_timestamp; + if (!dec->blocksize) + return GST_FLOW_NOT_NEGOTIATED; + + data = GST_BUFFER_DATA (buffer); + outbuf = adpcmdec_decode_block (dec, data, dec->blocksize); + + if (outbuf == NULL) { + GST_AUDIO_DECODER_ERROR (bdec, 1, STREAM, DECODE, (NULL), + ("frame decode failed"), ret); } - if (dec->blocksize > 0) { - gst_adapter_push (dec->adapter, buf); - - while (gst_adapter_available (dec->adapter) >= dec->blocksize) { - databuf = gst_adapter_take_buffer (dec->adapter, dec->blocksize); - data = GST_BUFFER_DATA (databuf); - - ret = adpcmdec_decode_block (dec, data, dec->blocksize); - - /* Done with input data, free it */ - gst_buffer_unref (databuf); - - if (ret != GST_FLOW_OK) - goto done; - } - } else { - /* No explicit blocksize; we just process one input buffer at a time */ - ret = adpcmdec_decode_block (dec, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf)); - gst_buffer_unref (buf); - } - -done: - gst_object_unref (dec); + if (ret == GST_FLOW_OK) + ret = gst_audio_decoder_finish_frame (bdec, outbuf, 1); return ret; } static gboolean -adpcmdec_sink_event (GstPad * pad, GstEvent * event) +adpcmdec_start (GstAudioDecoder * bdec) { - ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad); - gboolean res; - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - dec->out_samples = 0; - dec->timestamp = GST_CLOCK_TIME_NONE; - dec->base_timestamp = GST_CLOCK_TIME_NONE; - gst_adapter_clear (dec->adapter); - /* Fall through */ - default: - res = gst_pad_push_event (dec->srcpad, event); - break; - } - gst_object_unref (dec); - return res; + ADPCMDec *dec = (ADPCMDec *) bdec; + + GST_DEBUG_OBJECT (dec, "start"); + + dec->blocksize = 0; + dec->rate = 0; + dec->channels = 0; + + return TRUE; } -static GstStateChangeReturn -adpcmdec_change_state (GstElement * element, GstStateChange transition) +static gboolean +adpcmdec_stop (GstAudioDecoder * dec) { - GstStateChangeReturn ret; - ADPCMDec *dec = (ADPCMDec *) element; + GST_DEBUG_OBJECT (dec, "stop"); - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - 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: - adpcmdec_teardown (dec); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - return ret; -} - -static void -adpcmdec_dispose (GObject * obj) -{ - G_OBJECT_CLASS (parent_class)->dispose (obj); + return TRUE; } static void adpcmdec_init (ADPCMDec * dec, ADPCMDecClass * klass) { - dec->sinkpad = - gst_pad_new_from_static_template (&adpcmdec_sink_template, "sink"); - gst_pad_set_setcaps_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (adpcmdec_sink_setcaps)); - gst_pad_set_chain_function (dec->sinkpad, GST_DEBUG_FUNCPTR (adpcmdec_chain)); - gst_pad_set_event_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (adpcmdec_sink_event)); - gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); - dec->srcpad = - gst_pad_new_from_static_template (&adpcmdec_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); } static void adpcmdec_class_init (ADPCMDecClass * klass) { - GObjectClass *gobjectclass = (GObjectClass *) klass; - GstElementClass *gstelement_class = (GstElementClass *) klass; - gobjectclass->dispose = adpcmdec_dispose; - gstelement_class->change_state = adpcmdec_change_state; -} static void + GstAudioDecoderClass *base_class = (GstAudioDecoderClass *) klass; + base_class->start = GST_DEBUG_FUNCPTR (adpcmdec_start); + base_class->stop = GST_DEBUG_FUNCPTR (adpcmdec_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (adpcmdec_set_format); + base_class->parse = GST_DEBUG_FUNCPTR (adpcmdec_parse); + base_class->handle_frame = GST_DEBUG_FUNCPTR (adpcmdec_handle_frame); +} + +static void adpcmdec_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); From 9b31cade1e9449565a3683eb2b6ababc55c8f755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 19 Jan 2012 15:12:46 +0000 Subject: [PATCH 18/57] Add --disable-fatal-warnings configure option --- common | 2 +- configure.ac | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/common b/common index 11f0cd5a3f..17fa4abf49 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 11f0cd5a3fba36f85cf3e434150bfe66b1bf08d4 +Subproject commit 17fa4abf49d31cf5dcc2994bdbaa86e45a3fb69f diff --git a/configure.ac b/configure.ac index 0a35b0be54..d7b3460c39 100644 --- a/configure.ac +++ b/configure.ac @@ -71,6 +71,8 @@ AG_GST_GETTEXT([gst-plugins-bad-$GST_MAJORMINOR]) dnl *** check for arguments to configure *** +AG_GST_ARG_DISABLE_FATAL_WARNINGS + AG_GST_ARG_DEBUG AG_GST_ARG_PROFILING AG_GST_ARG_VALGRIND @@ -274,14 +276,14 @@ AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO], dnl define an ERROR_CFLAGS Makefile variable dnl -Waggregate-return - libexif returns aggregates dnl -Wundef - Windows headers check _MSC_VER unconditionally -AG_GST_SET_ERROR_CFLAGS($GST_GIT, [ +AG_GST_SET_ERROR_CFLAGS($FATAL_WARNINGS, [ -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wwrite-strings -Wformat-security -Wold-style-definition -Winit-self -Wmissing-include-dirs -Waddress -Wno-multichar -Wnested-externs]) dnl define an ERROR_CXXFLAGS Makefile variable -AG_GST_SET_ERROR_CXXFLAGS($GST_GIT, [ +AG_GST_SET_ERROR_CXXFLAGS($FATAL_WARNINGS, [ -Wmissing-declarations -Wredundant-decls -Wwrite-strings -Wformat-nonliteral -Wformat-security -Winit-self -Wmissing-include-dirs -Waddress -Wno-multichar ]) From c6edc0463d964c89be5b0b51ae6b1a903cdc4b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 19 Jan 2012 15:43:51 +0000 Subject: [PATCH 19/57] gsmenc: fix unused-but-set-variable compiler warning --- ext/gsm/gstgsmenc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ext/gsm/gstgsmenc.c b/ext/gsm/gstgsmenc.c index ea8c43c288..d95968c943 100644 --- a/ext/gsm/gstgsmenc.c +++ b/ext/gsm/gstgsmenc.c @@ -136,11 +136,8 @@ gst_gsmenc_stop (GstAudioEncoder * enc) static gboolean gst_gsmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { - GstGSMEnc *gsmenc; GstCaps *srccaps; - gsmenc = GST_GSMENC (benc); - srccaps = gst_static_pad_template_get_caps (&gsmenc_src_template); gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (benc), srccaps); From 27354f065df047ca0d08a49daf15949d64426f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 10 Jan 2012 00:22:38 +0000 Subject: [PATCH 20/57] mpegpsdemux: handle corner-case of short read in pull_buffer better It's extremely unlikely, but there are corner cases where a short read might happen, so handle that, just in case. --- gst/mpegdemux/gstmpegdemux.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index 55a567eb03..7d5b139050 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -2387,7 +2387,7 @@ gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos, guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ); guint cursor, to_read = BLOCK_SZ; guint8 *data; - guint end_scan; + guint end_scan, data_size; do { if (offset + scan_sz > demux->sink_segment.stop) @@ -2401,8 +2401,14 @@ gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos, if (G_UNLIKELY (ret != GST_FLOW_OK)) return FALSE; + /* may get a short buffer at the end of the file */ + data_size = GST_BUFFER_SIZE (buffer); + if (G_UNLIKELY (data_size <= scan_sz)) + return FALSE; + data = GST_BUFFER_DATA (buffer); - end_scan = GST_BUFFER_SIZE (buffer) - scan_sz; + end_scan = data_size - scan_sz; + /* scan the block */ for (cursor = 0; !found && cursor <= end_scan; cursor++) { found = gst_flups_demux_scan_ts (demux, data++, mode, &ts); @@ -2433,7 +2439,7 @@ gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos, guint64 ts = 0; guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ); guint cursor, to_read = BLOCK_SZ; - guint start_scan; + guint start_scan, data_size; guint8 *data; do { @@ -2451,8 +2457,14 @@ gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos, if (G_UNLIKELY (ret != GST_FLOW_OK)) return FALSE; - start_scan = GST_BUFFER_SIZE (buffer) - scan_sz; + /* may get a short buffer at the end of the file */ + data_size = GST_BUFFER_SIZE (buffer); + if (G_UNLIKELY (data_size <= scan_sz)) + return FALSE; + + start_scan = data_size - scan_sz; data = GST_BUFFER_DATA (buffer) + start_scan; + /* scan the block */ for (cursor = (start_scan + 1); !found && cursor > 0; cursor--) { found = gst_flups_demux_scan_ts (demux, data--, mode, &ts); From f3c812e06277a7534a4426999cc12b88f8e6374a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sun, 2 Jan 2011 19:34:04 +0000 Subject: [PATCH 21/57] chromaprint: import Acoustid audio fingerprinting plugin Imported from https://launchpad.net/gst-chromaprint --- configure.ac | 12 ++ ext/Makefile.am | 8 + ext/chromaprint/Makefile.am | 14 ++ ext/chromaprint/gstchromaprint.c | 322 +++++++++++++++++++++++++++++++ ext/chromaprint/gstchromaprint.h | 84 ++++++++ 5 files changed, 440 insertions(+) create mode 100644 ext/chromaprint/Makefile.am create mode 100644 ext/chromaprint/gstchromaprint.c create mode 100644 ext/chromaprint/gstchromaprint.h diff --git a/configure.ac b/configure.ac index d7b3460c39..7bdd03e94e 100644 --- a/configure.ac +++ b/configure.ac @@ -732,6 +732,16 @@ AG_GST_CHECK_FEATURE(CELT, [celt], celt, [ AC_SUBST(CELT_LIBS) ]) +dnl *** chromaprint *** +translit(dnm, m, l) AM_CONDITIONAL(USE_CHROMAPRINT, true) +AG_GST_CHECK_FEATURE(CHROMAPRINT, [chromaprint], chromaprint, [ + PKG_CHECK_MODULES(CHROMAPRINT, libchromaprint, HAVE_CHROMAPRINT="yes", [ + HAVE_CHROMAPRINT="no" + ]) + AC_SUBST(CHROMAPRINT_CFLAGS) + AC_SUBST(CHROMAPRINT_LIBS) +]) + dnl *** Cog *** translit(dnm, m, l) AM_CONDITIONAL(USE_COG, true) AG_GST_CHECK_FEATURE(COG, [Cog plugin], cog, [ @@ -1777,6 +1787,7 @@ AM_CONDITIONAL(USE_APEXSINK, false) AM_CONDITIONAL(USE_BZ2, false) AM_CONDITIONAL(USE_CDAUDIO, false) AM_CONDITIONAL(USE_CELT, false) +AM_CONDITIONAL(USE_CHROMAPRINT, false) AM_CONDITIONAL(USE_COG, false) AM_CONDITIONAL(USE_CURL, false) AM_CONDITIONAL(USE_DC1394, false) @@ -2034,6 +2045,7 @@ ext/apexsink/Makefile ext/bz2/Makefile ext/cdaudio/Makefile ext/celt/Makefile +ext/chromaprint/Makefile ext/cog/Makefile ext/curl/Makefile ext/dc1394/Makefile diff --git a/ext/Makefile.am b/ext/Makefile.am index dc62386cab..a1636f6904 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -58,6 +58,12 @@ else CELT_DIR= endif +if USE_CHROMAPRINT +CHROMAPRINT_DIR=chromaprint +else +CHROMAPRINT_DIR= +endif + if USE_COG COG_DIR=cog else @@ -397,6 +403,7 @@ SUBDIRS=\ $(BZ2_DIR) \ $(CDAUDIO_DIR) \ $(CELT_DIR) \ + $(CHROMAPRINT_DIR) \ $(COG_DIR) \ $(CURL_DIR) \ $(DC1394_DIR) \ @@ -456,6 +463,7 @@ DIST_SUBDIRS = \ bz2 \ cdaudio \ celt \ + chromaprint \ cog \ curl \ dc1394 \ diff --git a/ext/chromaprint/Makefile.am b/ext/chromaprint/Makefile.am new file mode 100644 index 0000000000..115d8c2988 --- /dev/null +++ b/ext/chromaprint/Makefile.am @@ -0,0 +1,14 @@ +plugin_LTLIBRARIES = libgstchromaprint.la + +libgstchromaprint_la_SOURCES = gstchromaprint.c gstchromaprint.h + +libgstchromaprint_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ + $(CHROMAPRINT_CFLAGS) +libgstchromaprint_la_LIBADD = \ + $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(GST_LIBS) \ + $(CHROMAPRINT_LIBS) +libgstchromaprint_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstchromaprint_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstchromaprint.h diff --git a/ext/chromaprint/gstchromaprint.c b/ext/chromaprint/gstchromaprint.c new file mode 100644 index 0000000000..2d6f9e7c48 --- /dev/null +++ b/ext/chromaprint/gstchromaprint.c @@ -0,0 +1,322 @@ +/* vim:si:et:sw=2:sts=2:ts=8 + * + * GStreamer + * + * gstchromaprint.c + * + * Copyright (C) 2006 M. Derezynski + * Copyright (C) 2008 Eric Buehl + * Copyright (C) 2008 Sebastian Dröge + * Copyright (C) 2011 Lukáš Lalinský + * + * 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. + */ + +/** + * SECTION:element-chromaprint + * + * FIXME:Describe chromaprint here. + * + * + * Example launch line + * |[ + * gst-launch -v -m fakesrc ! chromaprint ! fakesink silent=TRUE + * filesrc location= ! decodebin ! audioconvert ! chromaprint ! fakesink sync=0 silent=TRUE + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "gstchromaprint.h" + +#define DEFAULT_MAX_DURATION 120 + +#define PAD_CAPS \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, 2 ], " \ + "endianness = (int) { BYTE_ORDER }, " \ + "width = (int) { 16 }, " \ + "depth = (int) { 16 }, " \ + "signed = (boolean) true" + +GST_DEBUG_CATEGORY_STATIC (gst_chromaprint_debug); +#define GST_CAT_DEFAULT gst_chromaprint_debug + +enum +{ + PROP_0, + PROP_FINGERPRINT, + PROP_MAX_DURATION +}; + + +GST_BOILERPLATE (GstChromaprint, gst_chromaprint, GstElement, + GST_TYPE_AUDIO_FILTER); + +static void gst_chromaprint_finalize (GObject * object); +static void gst_chromaprint_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_chromaprint_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static GstFlowReturn gst_chromaprint_transform_ip (GstBaseTransform * trans, + GstBuffer * buf); +static gboolean gst_chromaprint_event (GstBaseTransform * trans, + GstEvent * event); + +/* GObject vmethod implementations */ + +static void +gst_chromaprint_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GstAudioFilterClass *audio_filter_class = (GstAudioFilterClass *) g_class; + GstCaps *caps; + + gst_element_class_set_details_simple (element_class, + "Chromaprint", + "Chromaprint fingerprinting element", + "Find an audio fingerprint using the Chromaprint library", + "Lukáš Lalinský "); + + caps = gst_caps_from_string (PAD_CAPS); + gst_audio_filter_class_add_pad_templates (audio_filter_class, caps); + gst_caps_unref (caps); +} + +static void +gst_chromaprint_class_init (GstChromaprintClass * klass) +{ + GObjectClass *gobject_class; + GstBaseTransformClass *gstbasetrans_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_chromaprint_set_property); + gobject_class->get_property = + GST_DEBUG_FUNCPTR (gst_chromaprint_get_property); + + g_object_class_install_property (gobject_class, PROP_FINGERPRINT, + g_param_spec_string ("fingerprint", "Resulting fingerprint", + "Resulting fingerprint", NULL, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_MAX_DURATION, + g_param_spec_uint ("duration", "Duration limit", + "Number of seconds of audio to use for fingerpriting", + 0, G_MAXUINT, DEFAULT_MAX_DURATION, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_chromaprint_finalize); + + gstbasetrans_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_chromaprint_transform_ip); + gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_chromaprint_event); + gstbasetrans_class->passthrough_on_same_caps = TRUE; +} + +static void +gst_chromaprint_reset (GstChromaprint * chromaprint) +{ + if (chromaprint->fingerprint) { + chromaprint_dealloc (chromaprint->fingerprint); + chromaprint->fingerprint = NULL; + } + + chromaprint->nsamples = 0; + chromaprint->duration = 0; + chromaprint->record = TRUE; +} + +static void +gst_chromaprint_create_fingerprint (GstChromaprint * chromaprint) +{ + GstTagList *tags; + + if (chromaprint->duration <= 3) + return; + + GST_DEBUG ("Generating fingerprint based on %d seconds of audio", + chromaprint->duration); + chromaprint_finish (chromaprint->context); + chromaprint_get_fingerprint (chromaprint->context, &chromaprint->fingerprint); + chromaprint->record = FALSE; + + tags = gst_tag_list_new (); + gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, + GST_TAG_CHROMAPRINT_FINGERPRINT, chromaprint->fingerprint, NULL); + gst_element_found_tags (GST_ELEMENT (chromaprint), tags); +} + +static void +gst_chromaprint_init (GstChromaprint * chromaprint, + GstChromaprintClass * gclass) +{ + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (chromaprint), TRUE); + + chromaprint->context = chromaprint_new (CHROMAPRINT_ALGORITHM_DEFAULT); + chromaprint->fingerprint = NULL; + chromaprint->max_duration = DEFAULT_MAX_DURATION; + gst_chromaprint_reset (chromaprint); +} + +static void +gst_chromaprint_finalize (GObject * object) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (object); + + chromaprint->record = FALSE; + + if (chromaprint->context) { + chromaprint_free (chromaprint->context); + chromaprint->context = NULL; + } + + if (chromaprint->fingerprint) { + chromaprint_dealloc (chromaprint->fingerprint); + chromaprint->fingerprint = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static GstFlowReturn +gst_chromaprint_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (trans); + guint nsamples; + gint rate = GST_AUDIO_FILTER (chromaprint)->format.rate; + gint channels = GST_AUDIO_FILTER (chromaprint)->format.channels; + + g_return_val_if_fail (rate > 0 && channels > 0, GST_FLOW_NOT_NEGOTIATED); + + if (!chromaprint->record) + return GST_FLOW_OK; + + nsamples = GST_BUFFER_SIZE (buf) / (channels * 2); + if (!nsamples) + return GST_FLOW_OK; + + if (!chromaprint->nsamples) { + chromaprint_start (chromaprint->context, rate, channels); + } + chromaprint->nsamples += nsamples; + chromaprint->duration = chromaprint->nsamples / rate; + + chromaprint_feed (chromaprint->context, GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf) / 2); + + if (chromaprint->duration >= chromaprint->max_duration + && !chromaprint->fingerprint) { + gst_chromaprint_create_fingerprint (chromaprint); + } + + return GST_FLOW_OK; +} + +static gboolean +gst_chromaprint_event (GstBaseTransform * trans, GstEvent * event) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (trans); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + case GST_EVENT_NEWSEGMENT: + GST_DEBUG ("Got %s event, clearing buffer", GST_EVENT_TYPE_NAME (event)); + gst_chromaprint_reset (chromaprint); + break; + case GST_EVENT_EOS: + if (!chromaprint->fingerprint) { + gst_chromaprint_create_fingerprint (chromaprint); + } + break; + default: + break; + } + + return TRUE; +} + +static void +gst_chromaprint_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (object); + + switch (prop_id) { + case PROP_MAX_DURATION: + chromaprint->max_duration = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_chromaprint_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (object); + + switch (prop_id) { + case PROP_FINGERPRINT: + g_value_set_string (value, chromaprint->fingerprint); + break; + case PROP_MAX_DURATION: + g_value_set_uint (value, chromaprint->max_duration); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean ret; + + GST_DEBUG_CATEGORY_INIT (gst_chromaprint_debug, "chromaprint", + 0, "chromaprint element"); + + GST_DEBUG ("libchromaprint %s", chromaprint_get_version ()); + + ret = gst_element_register (plugin, "chromaprint", GST_RANK_NONE, + GST_TYPE_CHROMAPRINT); + + if (ret) { + gst_tag_register (GST_TAG_CHROMAPRINT_FINGERPRINT, GST_TAG_FLAG_META, + G_TYPE_STRING, "chromaprint fingerprint", "Chromaprint fingerprint", + NULL); + } + + return ret; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "chromaprint", + "Calculate Chromaprint fingerprint from audio files", + plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/ext/chromaprint/gstchromaprint.h b/ext/chromaprint/gstchromaprint.h new file mode 100644 index 0000000000..892bacc870 --- /dev/null +++ b/ext/chromaprint/gstchromaprint.h @@ -0,0 +1,84 @@ +/* vim:si:et:sw=2:sts=2:ts=8 + * + * GStreamer + * + * gstchromaprint.h + * + * Copyright (C) 2006 M. Derezynski + * Copyright (C) 2008 Eric Buehl + * Copyright (C) 2008 Sebastian Dröge + * Copyright (C) 2011 Lukáš Lalinský <> + * + * 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_CHROMAPRINT_H__ +#define __GST_CHROMAPRINT_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CHROMAPRINT \ + (gst_chromaprint_get_type()) +#define GST_CHROMAPRINT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CHROMAPRINT,GstChromaprint)) +#define GST_CHROMAPRINT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CHROMAPRINT,GstChromaprintClass)) +#define GST_IS_CHROMAPRINT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CHROMAPRINT)) +#define GST_IS_CHROMAPRINT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CHROMAPRINT)) + +#define GST_TAG_CHROMAPRINT_FINGERPRINT "chromaprint-fingerprint" + +typedef struct _GstChromaprint GstChromaprint; +typedef struct _GstChromaprintClass GstChromaprintClass; + +/** + * GstChromaprint: + * + * Opaque #GstChromaprint data structure + */ + +struct _GstChromaprint +{ + GstAudioFilter element; + + /*< private > */ + + ChromaprintContext *context; + char *fingerprint; + gboolean record; + guint64 nsamples; + guint duration; + guint max_duration; +}; + +struct _GstChromaprintClass +{ + GstAudioFilterClass parent_class; +}; + +GType gst_chromaprint_get_type (void); + +G_END_DECLS + +#endif /* __GST_CHROMAPRINT_H__ */ From e601bf76e3318948ac8e595c5d7d67a3dc9245b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 20 Jan 2012 00:53:46 +0000 Subject: [PATCH 22/57] chromaprint: minor clean-ups Flesh out docs a bit, fix element class. --- ext/chromaprint/gstchromaprint.c | 63 +++++++++++++++----------------- ext/chromaprint/gstchromaprint.h | 29 ++++++--------- 2 files changed, 40 insertions(+), 52 deletions(-) diff --git a/ext/chromaprint/gstchromaprint.c b/ext/chromaprint/gstchromaprint.c index 2d6f9e7c48..c0a129301c 100644 --- a/ext/chromaprint/gstchromaprint.c +++ b/ext/chromaprint/gstchromaprint.c @@ -1,14 +1,9 @@ -/* vim:si:et:sw=2:sts=2:ts=8 - * - * GStreamer - * - * gstchromaprint.c - * +/* GStreamer chromaprint audio fingerprinting element * Copyright (C) 2006 M. Derezynski * Copyright (C) 2008 Eric Buehl * Copyright (C) 2008 Sebastian Dröge * Copyright (C) 2011 Lukáš Lalinský - * + * * 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 @@ -28,24 +23,23 @@ /** * SECTION:element-chromaprint * - * FIXME:Describe chromaprint here. + * The chromaprint element calculates an acoustic fingerprint for an + * audio stream which can be used to identify a song and look up + * further metadata from the Acoustid + * and Musicbrainz databases. * * * Example launch line * |[ - * gst-launch -v -m fakesrc ! chromaprint ! fakesink silent=TRUE - * filesrc location= ! decodebin ! audioconvert ! chromaprint ! fakesink sync=0 silent=TRUE + * gst-launch -m uridecodebin uri=file:///path/to/song.ogg ! audioconvert ! chromaprint ! fakesink * ]| * */ #ifdef HAVE_CONFIG_H -# include +#include #endif -#include -#include - #include "gstchromaprint.h" #define DEFAULT_MAX_DURATION 120 @@ -83,8 +77,6 @@ static GstFlowReturn gst_chromaprint_transform_ip (GstBaseTransform * trans, static gboolean gst_chromaprint_event (GstBaseTransform * trans, GstEvent * event); -/* GObject vmethod implementations */ - static void gst_chromaprint_base_init (gpointer g_class) { @@ -93,8 +85,8 @@ gst_chromaprint_base_init (gpointer g_class) GstCaps *caps; gst_element_class_set_details_simple (element_class, - "Chromaprint", "Chromaprint fingerprinting element", + "Filter/Analyzer/Audio", "Find an audio fingerprint using the Chromaprint library", "Lukáš Lalinský "); @@ -112,18 +104,17 @@ gst_chromaprint_class_init (GstChromaprintClass * klass) gobject_class = G_OBJECT_CLASS (klass); gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); - gobject_class->set_property = - GST_DEBUG_FUNCPTR (gst_chromaprint_set_property); - gobject_class->get_property = - GST_DEBUG_FUNCPTR (gst_chromaprint_get_property); + gobject_class->set_property = gst_chromaprint_set_property; + gobject_class->get_property = gst_chromaprint_get_property; + /* FIXME: do we need this in addition to the tag message ? */ g_object_class_install_property (gobject_class, PROP_FINGERPRINT, g_param_spec_string ("fingerprint", "Resulting fingerprint", "Resulting fingerprint", NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_MAX_DURATION, g_param_spec_uint ("duration", "Duration limit", - "Number of seconds of audio to use for fingerpriting", + "Number of seconds of audio to use for fingerprinting", 0, G_MAXUINT, DEFAULT_MAX_DURATION, G_PARAM_READABLE | G_PARAM_WRITABLE)); @@ -156,15 +147,17 @@ gst_chromaprint_create_fingerprint (GstChromaprint * chromaprint) if (chromaprint->duration <= 3) return; - GST_DEBUG ("Generating fingerprint based on %d seconds of audio", + GST_DEBUG_OBJECT (chromaprint, + "Generating fingerprint based on %d seconds of audio", chromaprint->duration); + chromaprint_finish (chromaprint->context); chromaprint_get_fingerprint (chromaprint->context, &chromaprint->fingerprint); chromaprint->record = FALSE; - tags = gst_tag_list_new (); - gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, - GST_TAG_CHROMAPRINT_FINGERPRINT, chromaprint->fingerprint, NULL); + tags = gst_tag_list_new_full (GST_TAG_CHROMAPRINT_FINGERPRINT, + chromaprint->fingerprint, NULL); + gst_element_found_tags (GST_ELEMENT (chromaprint), tags); } @@ -204,20 +197,22 @@ static GstFlowReturn gst_chromaprint_transform_ip (GstBaseTransform * trans, GstBuffer * buf) { GstChromaprint *chromaprint = GST_CHROMAPRINT (trans); - guint nsamples; gint rate = GST_AUDIO_FILTER (chromaprint)->format.rate; gint channels = GST_AUDIO_FILTER (chromaprint)->format.channels; + guint nsamples; - g_return_val_if_fail (rate > 0 && channels > 0, GST_FLOW_NOT_NEGOTIATED); + if (G_UNLIKELY (rate <= 0 || channels <= 0)) + return GST_FLOW_NOT_NEGOTIATED; if (!chromaprint->record) return GST_FLOW_OK; nsamples = GST_BUFFER_SIZE (buf) / (channels * 2); - if (!nsamples) + + if (nsamples == 0) return GST_FLOW_OK; - if (!chromaprint->nsamples) { + if (chromaprint->nsamples == 0) { chromaprint_start (chromaprint->context, rate, channels); } chromaprint->nsamples += nsamples; @@ -242,7 +237,8 @@ gst_chromaprint_event (GstBaseTransform * trans, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: case GST_EVENT_NEWSEGMENT: - GST_DEBUG ("Got %s event, clearing buffer", GST_EVENT_TYPE_NAME (event)); + GST_DEBUG_OBJECT (trans, "Got %s event, clearing buffer", + GST_EVENT_TYPE_NAME (event)); gst_chromaprint_reset (chromaprint); break; case GST_EVENT_EOS: @@ -292,7 +288,6 @@ gst_chromaprint_get_property (GObject * object, guint prop_id, } } - static gboolean plugin_init (GstPlugin * plugin) { @@ -301,7 +296,7 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (gst_chromaprint_debug, "chromaprint", 0, "chromaprint element"); - GST_DEBUG ("libchromaprint %s", chromaprint_get_version ()); + GST_INFO ("libchromaprint %s", chromaprint_get_version ()); ret = gst_element_register (plugin, "chromaprint", GST_RANK_NONE, GST_TYPE_CHROMAPRINT); @@ -319,4 +314,4 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "chromaprint", "Calculate Chromaprint fingerprint from audio files", - plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/chromaprint/gstchromaprint.h b/ext/chromaprint/gstchromaprint.h index 892bacc870..12bad8a139 100644 --- a/ext/chromaprint/gstchromaprint.h +++ b/ext/chromaprint/gstchromaprint.h @@ -1,14 +1,9 @@ -/* vim:si:et:sw=2:sts=2:ts=8 - * - * GStreamer - * - * gstchromaprint.h - * +/* GStreamer chromaprint audio fingerprinting element * Copyright (C) 2006 M. Derezynski * Copyright (C) 2008 Eric Buehl * Copyright (C) 2008 Sebastian Dröge * Copyright (C) 2011 Lukáš Lalinský <> - * + * * 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 @@ -55,24 +50,22 @@ typedef struct _GstChromaprintClass GstChromaprintClass; /** * GstChromaprint: * - * Opaque #GstChromaprint data structure + * Opaque #GstChromaprint element structure */ - struct _GstChromaprint { GstAudioFilter element; - /*< private > */ - - ChromaprintContext *context; - char *fingerprint; - gboolean record; - guint64 nsamples; - guint duration; - guint max_duration; + /*< private >*/ + ChromaprintContext * context; + char * fingerprint; + gboolean record; + guint64 nsamples; + guint duration; + guint max_duration; }; -struct _GstChromaprintClass +struct _GstChromaprintClass { GstAudioFilterClass parent_class; }; From ee0fc47447b8f4c4914925a930233608d1c917c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 20 Jan 2012 15:23:54 +0000 Subject: [PATCH 23/57] configure: only check for gst-plugins-{good,ugly,ffmpeg} in uninstalled setups We don't install .pc files for plugin modules, because we only need them in uninstalled setups, so we can find the plugins for unit tests (even when run a couple of directories deeper or out-of-tree during make distcheck). Try to avoid confusion, so only check for those if this is in fact an uninstalled setup. For installed setups there's no problem finding the plugins, we assume they are all in the plugindir specified by GStreamer core's .pc file. https://bugzilla.gnome.org/show_bug.cgi?id=668311 --- common | 2 +- configure.ac | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/common b/common index 17fa4abf49..7604bab58b 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 17fa4abf49d31cf5dcc2994bdbaa86e45a3fb69f +Subproject commit 7604bab58b5dfc9370d506952f0407fb75c00388 diff --git a/configure.ac b/configure.ac index 7bdd03e94e..9d5d9522c6 100644 --- a/configure.ac +++ b/configure.ac @@ -196,9 +196,12 @@ AM_CONDITIONAL(HAVE_GST_CHECK, test "x$HAVE_GST_CHECK" = "xyes") AG_GST_CHECK_GST_PLUGINS_BASE($GST_MAJORMINOR, [$GSTPB_REQ], yes) dnl check for uninstalled plugin directories for unit tests -AG_GST_CHECK_GST_PLUGINS_GOOD($GST_MAJORMINOR, [0.10.25]) -AG_GST_CHECK_GST_PLUGINS_UGLY($GST_MAJORMINOR, [0.10.16]) -AG_GST_CHECK_GST_PLUGINS_FFMPEG($GST_MAJORMINOR, [0.10.11]) +dnl skip these checks for normal installed setups to avoid confusion +AG_GST_CHECK_UNINSTALLED_SETUP([ + AG_GST_CHECK_GST_PLUGINS_GOOD($GST_MAJORMINOR, [0.10.25]) + AG_GST_CHECK_GST_PLUGINS_UGLY($GST_MAJORMINOR, [0.10.16]) + AG_GST_CHECK_GST_PLUGINS_FFMPEG($GST_MAJORMINOR, [0.10.11]) +]) dnl Check for documentation xrefs GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`" From c92efe38e9f3e60509449ce1bb0d5a6d880c337a Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Wed, 18 Jan 2012 16:35:16 +0100 Subject: [PATCH 24/57] codecparsers: h264: fix ref_pic_list_modification() The entries were not filled in linearly and the termination was not recorded either. Now, the actual number of modifications is recorded similarly to dec_ref_pic_marking(). i.e. an explicit counter instead of storing the termination value in the array. https://bugzilla.gnome.org/show_bug.cgi?id=668192 --- gst-libs/gst/codecparsers/gsth264parser.c | 13 +++++++++---- gst-libs/gst/codecparsers/gsth264parser.h | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 6a164ecb1f..45039f780e 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -747,22 +747,26 @@ slice_parse_ref_pic_list_modification_1 (GstH264SliceHdr * slice, NalReader * nr, guint list) { GstH264RefPicListModification *entries; - guint8 *ref_pic_list_modification_flag; + guint8 *ref_pic_list_modification_flag, *n_ref_pic_list_modification; guint32 modification_of_pic_nums_idc; guint i = 0; if (list == 0) { entries = slice->ref_pic_list_modification_l0; ref_pic_list_modification_flag = &slice->ref_pic_list_modification_flag_l0; + n_ref_pic_list_modification = &slice->n_ref_pic_list_modification_l0; } else { entries = slice->ref_pic_list_modification_l1; ref_pic_list_modification_flag = &slice->ref_pic_list_modification_flag_l1; + n_ref_pic_list_modification = &slice->n_ref_pic_list_modification_l1; } READ_UINT8 (nr, *ref_pic_list_modification_flag, 1); if (*ref_pic_list_modification_flag) { - do { + while (1) { READ_UE (nr, modification_of_pic_nums_idc); + if (modification_of_pic_nums_idc == 3) + break; if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) { READ_UE_ALLOWED (nr, entries[i].value.abs_diff_pic_num_minus1, 0, @@ -770,9 +774,10 @@ slice_parse_ref_pic_list_modification_1 (GstH264SliceHdr * slice, } else if (modification_of_pic_nums_idc == 2) { READ_UE (nr, entries[i].value.long_term_pic_num); } - } while (modification_of_pic_nums_idc != 3); + entries[i++].modification_of_pic_nums_idc = modification_of_pic_nums_idc; + } } - + *n_ref_pic_list_modification = i; return TRUE; error: diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h index d58f1b07dd..3c221560e8 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.h +++ b/gst-libs/gst/codecparsers/gsth264parser.h @@ -573,8 +573,10 @@ struct _GstH264SliceHdr guint8 num_ref_idx_l1_active_minus1; guint8 ref_pic_list_modification_flag_l0; + guint8 n_ref_pic_list_modification_l0; GstH264RefPicListModification ref_pic_list_modification_l0[32]; guint8 ref_pic_list_modification_flag_l1; + guint8 n_ref_pic_list_modification_l1; GstH264RefPicListModification ref_pic_list_modification_l1[32]; GstH264PredWeightTable pred_weight_table; From 6786f8c7bfafad5a95a7b257a233dae2fdcfc913 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 4 Aug 2011 13:05:22 -0700 Subject: [PATCH 25/57] kateenc: Don't error on empty input buffers --- ext/kate/gstkateenc.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/ext/kate/gstkateenc.c b/ext/kate/gstkateenc.c index e378a5cf37..8b782c6a17 100644 --- a/ext/kate/gstkateenc.c +++ b/ext/kate/gstkateenc.c @@ -952,27 +952,25 @@ gst_kate_enc_chain_text (GstKateEnc * ke, GstBuffer * buf, rflow = GST_FLOW_ERROR; } else { const char *text = (const char *) GST_BUFFER_DATA (buf); - if (text) { - size_t text_len = GST_BUFFER_SIZE (buf); - kate_float t0 = start / (double) GST_SECOND; - kate_float t1 = stop / (double) GST_SECOND; - GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f", - (int) text_len, (int) text_len, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf), t0, t1); - ret = kate_encode_text (&ke->k, t0, t1, text, text_len, &kp); - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to encode text: %d", ret)); - rflow = GST_FLOW_ERROR; - } else { - rflow = - gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1); - } - } else { - /* FIXME: this should not be an error, we should ignore it and move on */ + size_t text_len = GST_BUFFER_SIZE (buf); + kate_float t0 = start / (double) GST_SECOND; + kate_float t1 = stop / (double) GST_SECOND; + + if (text == NULL) { + text = ""; + text_len = 0; + } + + GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f", + (int) text_len, (int) text_len, GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf), t0, t1); + ret = kate_encode_text (&ke->k, t0, t1, text, text_len, &kp); + if (G_UNLIKELY (ret < 0)) { GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("no text in text packet")); + ("Failed to encode text: %d", ret)); rflow = GST_FLOW_ERROR; + } else { + rflow = gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1); } } From f02ee5b4036c63971c980034a98f0134f7e8dda5 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Tue, 9 Aug 2011 09:19:10 -0700 Subject: [PATCH 26/57] inter: Add subtitle inter elements --- gst/inter/Makefile.am | 4 + gst/inter/gstinter.c | 8 +- gst/inter/gstintersubsink.c | 329 ++++++++++++++++++++++++++ gst/inter/gstintersubsink.h | 57 +++++ gst/inter/gstintersubsrc.c | 455 ++++++++++++++++++++++++++++++++++++ gst/inter/gstintersubsrc.h | 57 +++++ gst/inter/gstintersurface.h | 1 + 7 files changed, 910 insertions(+), 1 deletion(-) create mode 100644 gst/inter/gstintersubsink.c create mode 100644 gst/inter/gstintersubsink.h create mode 100644 gst/inter/gstintersubsrc.c create mode 100644 gst/inter/gstintersubsrc.h diff --git a/gst/inter/Makefile.am b/gst/inter/Makefile.am index 4a7e78aeae..7728de9915 100644 --- a/gst/inter/Makefile.am +++ b/gst/inter/Makefile.am @@ -5,6 +5,8 @@ noinst_PROGRAMS = gstintertest libgstinter_la_SOURCES = \ gstinteraudiosink.c \ gstinteraudiosrc.c \ + gstintersubsink.c \ + gstintersubsrc.c \ gstintervideosink.c \ gstintervideosrc.c \ gstinter.c \ @@ -13,6 +15,8 @@ libgstinter_la_SOURCES = \ noinst_HEADERS = \ gstinteraudiosink.h \ gstinteraudiosrc.h \ + gstintersubsink.h \ + gstintersubsrc.h \ gstintervideosink.h \ gstintervideosrc.h \ gstintersurface.h diff --git a/gst/inter/gstinter.c b/gst/inter/gstinter.c index 60c5bd6a79..bae82bc0fd 100644 --- a/gst/inter/gstinter.c +++ b/gst/inter/gstinter.c @@ -1,5 +1,5 @@ /* GStreamer - * Copyright (C) 2011 David A. Schleef + * Copyright (C) 2011 David Schleef * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,6 +23,8 @@ #include "gstinteraudiosrc.h" #include "gstinteraudiosink.h" +#include "gstintersubsrc.h" +#include "gstintersubsink.h" #include "gstintervideosrc.h" #include "gstintervideosink.h" #include "gstintersurface.h" @@ -34,6 +36,10 @@ plugin_init (GstPlugin * plugin) GST_TYPE_INTER_AUDIO_SRC); gst_element_register (plugin, "interaudiosink", GST_RANK_NONE, GST_TYPE_INTER_AUDIO_SINK); + gst_element_register (plugin, "intersubsrc", GST_RANK_NONE, + GST_TYPE_INTER_SUB_SRC); + gst_element_register (plugin, "intersubsink", GST_RANK_NONE, + GST_TYPE_INTER_SUB_SINK); gst_element_register (plugin, "intervideosrc", GST_RANK_NONE, GST_TYPE_INTER_VIDEO_SRC); gst_element_register (plugin, "intervideosink", GST_RANK_NONE, diff --git a/gst/inter/gstintersubsink.c b/gst/inter/gstintersubsink.c new file mode 100644 index 0000000000..a5738767e3 --- /dev/null +++ b/gst/inter/gstintersubsink.c @@ -0,0 +1,329 @@ +/* GStreamer + * Copyright (C) 2011 David Schleef + * + * 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 Street, Suite 500, + * Boston, MA 02110-1335, USA. + */ +/** + * SECTION:element-gstintersubsink + * + * The intersubsink element does FIXME stuff. + * + * + * Example launch line + * |[ + * gst-launch -v fakesrc ! intersubsink ! FIXME ! fakesink + * ]| + * FIXME Describe what the pipeline does. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "gstintersubsink.h" + +GST_DEBUG_CATEGORY_STATIC (gst_inter_sub_sink_debug_category); +#define GST_CAT_DEFAULT gst_inter_sub_sink_debug_category + +/* prototypes */ + + +static void gst_inter_sub_sink_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_inter_sub_sink_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_inter_sub_sink_dispose (GObject * object); +static void gst_inter_sub_sink_finalize (GObject * object); + +static GstCaps *gst_inter_sub_sink_get_caps (GstBaseSink * sink); +static gboolean gst_inter_sub_sink_set_caps (GstBaseSink * sink, + GstCaps * caps); +static GstFlowReturn gst_inter_sub_sink_buffer_alloc (GstBaseSink * sink, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); +static void gst_inter_sub_sink_get_times (GstBaseSink * sink, + GstBuffer * buffer, GstClockTime * start, GstClockTime * end); +static gboolean gst_inter_sub_sink_start (GstBaseSink * sink); +static gboolean gst_inter_sub_sink_stop (GstBaseSink * sink); +static gboolean gst_inter_sub_sink_unlock (GstBaseSink * sink); +static gboolean gst_inter_sub_sink_event (GstBaseSink * sink, GstEvent * event); +static GstFlowReturn +gst_inter_sub_sink_preroll (GstBaseSink * sink, GstBuffer * buffer); +static GstFlowReturn +gst_inter_sub_sink_render (GstBaseSink * sink, GstBuffer * buffer); +static GstStateChangeReturn gst_inter_sub_sink_async_play (GstBaseSink * sink); +static gboolean gst_inter_sub_sink_activate_pull (GstBaseSink * sink, + gboolean active); +static gboolean gst_inter_sub_sink_unlock_stop (GstBaseSink * sink); + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate gst_inter_sub_sink_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("text/plain") + ); + + +/* class initialization */ + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_inter_sub_sink_debug_category, "intersubsink", 0, \ + "debug category for intersubsink element"); + +GST_BOILERPLATE_FULL (GstInterSubSink, gst_inter_sub_sink, GstBaseSink, + GST_TYPE_BASE_SINK, DEBUG_INIT); + +static void +gst_inter_sub_sink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_inter_sub_sink_sink_template)); + + gst_element_class_set_details_simple (element_class, "FIXME Long name", + "Generic", "FIXME Description", "FIXME "); +} + +static void +gst_inter_sub_sink_class_init (GstInterSubSinkClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseSinkClass *base_sink_class = GST_BASE_SINK_CLASS (klass); + + gobject_class->set_property = gst_inter_sub_sink_set_property; + gobject_class->get_property = gst_inter_sub_sink_get_property; + gobject_class->dispose = gst_inter_sub_sink_dispose; + gobject_class->finalize = gst_inter_sub_sink_finalize; + base_sink_class->get_caps = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_get_caps); + base_sink_class->set_caps = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_set_caps); + if (0) + base_sink_class->buffer_alloc = + GST_DEBUG_FUNCPTR (gst_inter_sub_sink_buffer_alloc); + base_sink_class->get_times = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_get_times); + base_sink_class->start = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_start); + base_sink_class->stop = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_stop); + base_sink_class->unlock = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_unlock); + if (0) + base_sink_class->event = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_event); + base_sink_class->preroll = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_preroll); + base_sink_class->render = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_render); + if (0) + base_sink_class->async_play = + GST_DEBUG_FUNCPTR (gst_inter_sub_sink_async_play); + if (0) + base_sink_class->activate_pull = + GST_DEBUG_FUNCPTR (gst_inter_sub_sink_activate_pull); + base_sink_class->unlock_stop = + GST_DEBUG_FUNCPTR (gst_inter_sub_sink_unlock_stop); + +} + +static void +gst_inter_sub_sink_init (GstInterSubSink * intersubsink, + GstInterSubSinkClass * intersubsink_class) +{ + + intersubsink->sinkpad = + gst_pad_new_from_static_template (&gst_inter_sub_sink_sink_template, + "sink"); + + intersubsink->surface = gst_inter_surface_get ("default"); + + intersubsink->fps_n = 1; + intersubsink->fps_d = 1; +} + +void +gst_inter_sub_sink_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + /* GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (object); */ + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_inter_sub_sink_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + /* GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (object); */ + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_inter_sub_sink_dispose (GObject * object) +{ + /* GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (object); */ + + /* clean up as possible. may be called multiple times */ + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +void +gst_inter_sub_sink_finalize (GObject * object) +{ + /* GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (object); */ + + /* clean up object here */ + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + + +static GstCaps * +gst_inter_sub_sink_get_caps (GstBaseSink * sink) +{ + + return NULL; +} + +static gboolean +gst_inter_sub_sink_set_caps (GstBaseSink * sink, GstCaps * caps) +{ + + return FALSE; +} + +static GstFlowReturn +gst_inter_sub_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size, + GstCaps * caps, GstBuffer ** buf) +{ + + return GST_FLOW_ERROR; +} + +static void +gst_inter_sub_sink_get_times (GstBaseSink * sink, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (sink); + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) { + *start = GST_BUFFER_TIMESTAMP (buffer); + if (GST_BUFFER_DURATION_IS_VALID (buffer)) { + *end = *start + GST_BUFFER_DURATION (buffer); + } else { + if (intersubsink->fps_n > 0) { + *end = *start + + gst_util_uint64_scale_int (GST_SECOND, intersubsink->fps_d, + intersubsink->fps_n); + } + } + } + + +} + +static gboolean +gst_inter_sub_sink_start (GstBaseSink * sink) +{ + + return TRUE; +} + +static gboolean +gst_inter_sub_sink_stop (GstBaseSink * sink) +{ + GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (sink); + + g_mutex_lock (intersubsink->surface->mutex); + if (intersubsink->surface->sub_buffer) { + gst_buffer_unref (intersubsink->surface->sub_buffer); + } + intersubsink->surface->sub_buffer = NULL; + g_mutex_unlock (intersubsink->surface->mutex); + + return TRUE; +} + +static gboolean +gst_inter_sub_sink_unlock (GstBaseSink * sink) +{ + + return TRUE; +} + +static gboolean +gst_inter_sub_sink_event (GstBaseSink * sink, GstEvent * event) +{ + + return TRUE; +} + +static GstFlowReturn +gst_inter_sub_sink_preroll (GstBaseSink * sink, GstBuffer * buffer) +{ + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_inter_sub_sink_render (GstBaseSink * sink, GstBuffer * buffer) +{ + GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (sink); + + g_mutex_lock (intersubsink->surface->mutex); + if (intersubsink->surface->sub_buffer) { + gst_buffer_unref (intersubsink->surface->sub_buffer); + } + intersubsink->surface->sub_buffer = gst_buffer_ref (buffer); + //intersubsink->surface->sub_buffer_count = 0; + g_mutex_unlock (intersubsink->surface->mutex); + + return GST_FLOW_OK; +} + +static GstStateChangeReturn +gst_inter_sub_sink_async_play (GstBaseSink * sink) +{ + + return GST_STATE_CHANGE_SUCCESS; +} + +static gboolean +gst_inter_sub_sink_activate_pull (GstBaseSink * sink, gboolean active) +{ + + return TRUE; +} + +static gboolean +gst_inter_sub_sink_unlock_stop (GstBaseSink * sink) +{ + + return TRUE; +} diff --git a/gst/inter/gstintersubsink.h b/gst/inter/gstintersubsink.h new file mode 100644 index 0000000000..be2da9b3b2 --- /dev/null +++ b/gst/inter/gstintersubsink.h @@ -0,0 +1,57 @@ +/* GStreamer + * Copyright (C) 2011 David Schleef + * + * 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_INTER_SUB_SINK_H_ +#define _GST_INTER_SUB_SINK_H_ + +#include +#include "gstintersurface.h" + +G_BEGIN_DECLS + +#define GST_TYPE_INTER_SUB_SINK (gst_inter_sub_sink_get_type()) +#define GST_INTER_SUB_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_INTER_SUB_SINK,GstInterSubSink)) +#define GST_INTER_SUB_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_INTER_SUB_SINK,GstInterSubSinkClass)) +#define GST_IS_INTER_SUB_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_INTER_SUB_SINK)) +#define GST_IS_INTER_SUB_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_INTER_SUB_SINK)) + +typedef struct _GstInterSubSink GstInterSubSink; +typedef struct _GstInterSubSinkClass GstInterSubSinkClass; + +struct _GstInterSubSink +{ + GstBaseSink base_intersubsink; + + GstPad *sinkpad; + GstInterSurface *surface; + + int fps_n; + int fps_d; +}; + +struct _GstInterSubSinkClass +{ + GstBaseSinkClass base_intersubsink_class; +}; + +GType gst_inter_sub_sink_get_type (void); + +G_END_DECLS + +#endif diff --git a/gst/inter/gstintersubsrc.c b/gst/inter/gstintersubsrc.c new file mode 100644 index 0000000000..60a29b3d75 --- /dev/null +++ b/gst/inter/gstintersubsrc.c @@ -0,0 +1,455 @@ +/* GStreamer + * Copyright (C) 2011 David Schleef + * + * 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 Street, Suite 500, + * Boston, MA 02110-1335, USA. + */ +/** + * SECTION:element-gstintersubsrc + * + * The intersubsrc element is a subtitle source element. It is used + * in connection with a intersubsink element in a different pipeline, + * similar to interaudiosink and interaudiosrc. + * + * + * Example launch line + * |[ + * gst-launch -v intersubsrc ! kateenc ! oggmux ! filesink location=out.ogv + * ]| + * + * The intersubsrc element cannot be used effectively with gst-launch, + * as it requires a second pipeline in the application to send subtitles. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "gstintersubsrc.h" + +GST_DEBUG_CATEGORY_STATIC (gst_inter_sub_src_debug_category); +#define GST_CAT_DEFAULT gst_inter_sub_src_debug_category + +/* prototypes */ + + +static void gst_inter_sub_src_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_inter_sub_src_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_inter_sub_src_dispose (GObject * object); +static void gst_inter_sub_src_finalize (GObject * object); + +static GstCaps *gst_inter_sub_src_get_caps (GstBaseSrc * src); +static gboolean gst_inter_sub_src_set_caps (GstBaseSrc * src, GstCaps * caps); +static gboolean gst_inter_sub_src_negotiate (GstBaseSrc * src); +static gboolean gst_inter_sub_src_newsegment (GstBaseSrc * src); +static gboolean gst_inter_sub_src_start (GstBaseSrc * src); +static gboolean gst_inter_sub_src_stop (GstBaseSrc * src); +static void +gst_inter_sub_src_get_times (GstBaseSrc * src, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end); +static gboolean gst_inter_sub_src_is_seekable (GstBaseSrc * src); +static gboolean gst_inter_sub_src_unlock (GstBaseSrc * src); +static gboolean gst_inter_sub_src_event (GstBaseSrc * src, GstEvent * event); +static GstFlowReturn +gst_inter_sub_src_create (GstBaseSrc * src, guint64 offset, guint size, + GstBuffer ** buf); +static gboolean gst_inter_sub_src_do_seek (GstBaseSrc * src, + GstSegment * segment); +static gboolean gst_inter_sub_src_query (GstBaseSrc * src, GstQuery * query); +static gboolean gst_inter_sub_src_check_get_range (GstBaseSrc * src); +static void gst_inter_sub_src_fixate (GstBaseSrc * src, GstCaps * caps); +static gboolean gst_inter_sub_src_unlock_stop (GstBaseSrc * src); +static gboolean +gst_inter_sub_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek, + GstSegment * segment); + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate gst_inter_sub_src_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + + +/* class initialization */ + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_inter_sub_src_debug_category, "intersubsrc", 0, \ + "debug category for intersubsrc element"); + +GST_BOILERPLATE_FULL (GstInterSubSrc, gst_inter_sub_src, GstBaseSrc, + GST_TYPE_BASE_SRC, DEBUG_INIT); + +static void +gst_inter_sub_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_inter_sub_src_src_template)); + + gst_element_class_set_details_simple (element_class, + "Inter-pipeline subtitle source", + "Source/Subtitle", "Inter-pipeline subtitle source", + "David Schleef "); +} + +static void +gst_inter_sub_src_class_init (GstInterSubSrcClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseSrcClass *base_src_class = GST_BASE_SRC_CLASS (klass); + + gobject_class->set_property = gst_inter_sub_src_set_property; + gobject_class->get_property = gst_inter_sub_src_get_property; + gobject_class->dispose = gst_inter_sub_src_dispose; + gobject_class->finalize = gst_inter_sub_src_finalize; + if (0) + base_src_class->get_caps = GST_DEBUG_FUNCPTR (gst_inter_sub_src_get_caps); + base_src_class->set_caps = GST_DEBUG_FUNCPTR (gst_inter_sub_src_set_caps); + if (0) + base_src_class->negotiate = GST_DEBUG_FUNCPTR (gst_inter_sub_src_negotiate); + if (0) + base_src_class->newsegment = + GST_DEBUG_FUNCPTR (gst_inter_sub_src_newsegment); + base_src_class->start = GST_DEBUG_FUNCPTR (gst_inter_sub_src_start); + base_src_class->stop = GST_DEBUG_FUNCPTR (gst_inter_sub_src_stop); + base_src_class->get_times = GST_DEBUG_FUNCPTR (gst_inter_sub_src_get_times); + if (0) + base_src_class->is_seekable = + GST_DEBUG_FUNCPTR (gst_inter_sub_src_is_seekable); + base_src_class->unlock = GST_DEBUG_FUNCPTR (gst_inter_sub_src_unlock); + base_src_class->event = GST_DEBUG_FUNCPTR (gst_inter_sub_src_event); + base_src_class->create = GST_DEBUG_FUNCPTR (gst_inter_sub_src_create); + if (0) + base_src_class->do_seek = GST_DEBUG_FUNCPTR (gst_inter_sub_src_do_seek); + base_src_class->query = GST_DEBUG_FUNCPTR (gst_inter_sub_src_query); + if (0) + base_src_class->check_get_range = + GST_DEBUG_FUNCPTR (gst_inter_sub_src_check_get_range); + base_src_class->fixate = GST_DEBUG_FUNCPTR (gst_inter_sub_src_fixate); + if (0) + base_src_class->unlock_stop = + GST_DEBUG_FUNCPTR (gst_inter_sub_src_unlock_stop); + if (0) + base_src_class->prepare_seek_segment = + GST_DEBUG_FUNCPTR (gst_inter_sub_src_prepare_seek_segment); + + +} + +static void +gst_inter_sub_src_init (GstInterSubSrc * intersubsrc, + GstInterSubSrcClass * intersubsrc_class) +{ + + intersubsrc->srcpad = + gst_pad_new_from_static_template (&gst_inter_sub_src_src_template, "src"); + + gst_base_src_set_format (GST_BASE_SRC (intersubsrc), GST_FORMAT_TIME); + gst_base_src_set_live (GST_BASE_SRC (intersubsrc), TRUE); + + intersubsrc->surface = gst_inter_surface_get ("default"); +} + +void +gst_inter_sub_src_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + /* GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (object); */ + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_inter_sub_src_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + /* GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (object); */ + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_inter_sub_src_dispose (GObject * object) +{ + /* GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (object); */ + + /* clean up as possible. may be called multiple times */ + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +void +gst_inter_sub_src_finalize (GObject * object) +{ + /* GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (object); */ + + /* clean up object here */ + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +static GstCaps * +gst_inter_sub_src_get_caps (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "get_caps"); + + return NULL; +} + +static gboolean +gst_inter_sub_src_set_caps (GstBaseSrc * src, GstCaps * caps) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "set_caps"); + + return TRUE; +} + +static gboolean +gst_inter_sub_src_negotiate (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "negotiate"); + + return TRUE; +} + +static gboolean +gst_inter_sub_src_newsegment (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "newsegment"); + + return TRUE; +} + +static gboolean +gst_inter_sub_src_start (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "start"); + + return TRUE; +} + +static gboolean +gst_inter_sub_src_stop (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "stop"); + + return TRUE; +} + +static void +gst_inter_sub_src_get_times (GstBaseSrc * src, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "get_times"); + + /* for live sources, sync on the timestamp of the buffer */ + if (gst_base_src_is_live (src)) { + GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* get duration to calculate end time */ + GstClockTime duration = GST_BUFFER_DURATION (buffer); + + if (GST_CLOCK_TIME_IS_VALID (duration)) { + *end = timestamp + duration; + } + *start = timestamp; + } + } else { + *start = -1; + *end = -1; + } +} + +static gboolean +gst_inter_sub_src_is_seekable (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "is_seekable"); + + return FALSE; +} + +static gboolean +gst_inter_sub_src_unlock (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "unlock"); + + return TRUE; +} + +static gboolean +gst_inter_sub_src_event (GstBaseSrc * src, GstEvent * event) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "event"); + + return TRUE; +} + +static GstFlowReturn +gst_inter_sub_src_create (GstBaseSrc * src, guint64 offset, guint size, + GstBuffer ** buf) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + GstBuffer *buffer; + + GST_DEBUG_OBJECT (intersubsrc, "create"); + + buffer = NULL; + + g_mutex_lock (intersubsrc->surface->mutex); + if (intersubsrc->surface->sub_buffer) { + buffer = gst_buffer_ref (intersubsrc->surface->sub_buffer); + //intersubsrc->surface->sub_buffer_count++; + //if (intersubsrc->surface->sub_buffer_count >= 30) { + gst_buffer_unref (intersubsrc->surface->sub_buffer); + intersubsrc->surface->sub_buffer = NULL; + //} + } + g_mutex_unlock (intersubsrc->surface->mutex); + + if (buffer == NULL) { + guint8 *data; + + buffer = gst_buffer_new_and_alloc (1); + + data = GST_BUFFER_DATA (buffer); + data[0] = 0; + } + + buffer = gst_buffer_make_metadata_writable (buffer); + + GST_BUFFER_TIMESTAMP (buffer) = + gst_util_uint64_scale_int (GST_SECOND, intersubsrc->n_frames, + intersubsrc->rate); + GST_DEBUG_OBJECT (intersubsrc, "create ts %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + GST_BUFFER_DURATION (buffer) = + gst_util_uint64_scale_int (GST_SECOND, (intersubsrc->n_frames + 1), + intersubsrc->rate) - GST_BUFFER_TIMESTAMP (buffer); + GST_BUFFER_OFFSET (buffer) = intersubsrc->n_frames; + GST_BUFFER_OFFSET_END (buffer) = -1; + GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT); + if (intersubsrc->n_frames == 0) { + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + } + gst_buffer_set_caps (buffer, GST_PAD_CAPS (GST_BASE_SRC_PAD (intersubsrc))); + intersubsrc->n_frames++; + + *buf = buffer; + + return GST_FLOW_OK; +} + +static gboolean +gst_inter_sub_src_do_seek (GstBaseSrc * src, GstSegment * segment) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "do_seek"); + + return FALSE; +} + +static gboolean +gst_inter_sub_src_query (GstBaseSrc * src, GstQuery * query) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "query"); + + return TRUE; +} + +static gboolean +gst_inter_sub_src_check_get_range (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "get_range"); + + return FALSE; +} + +static void +gst_inter_sub_src_fixate (GstBaseSrc * src, GstCaps * caps) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "fixate"); +} + +static gboolean +gst_inter_sub_src_unlock_stop (GstBaseSrc * src) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "stop"); + + return TRUE; +} + +static gboolean +gst_inter_sub_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek, + GstSegment * segment) +{ + GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src); + + GST_DEBUG_OBJECT (intersubsrc, "seek_segment"); + + return FALSE; +} diff --git a/gst/inter/gstintersubsrc.h b/gst/inter/gstintersubsrc.h new file mode 100644 index 0000000000..74bfed1e75 --- /dev/null +++ b/gst/inter/gstintersubsrc.h @@ -0,0 +1,57 @@ +/* GStreamer + * Copyright (C) 2011 David Schleef + * + * 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_INTER_SUB_SRC_H_ +#define _GST_INTER_SUB_SRC_H_ + +#include +#include "gstintersurface.h" + +G_BEGIN_DECLS + +#define GST_TYPE_INTER_SUB_SRC (gst_inter_sub_src_get_type()) +#define GST_INTER_SUB_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_INTER_SUB_SRC,GstInterSubSrc)) +#define GST_INTER_SUB_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_INTER_SUB_SRC,GstInterSubSrcClass)) +#define GST_IS_INTER_SUB_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_INTER_SUB_SRC)) +#define GST_IS_INTER_SUB_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_INTER_SUB_SRC)) + +typedef struct _GstInterSubSrc GstInterSubSrc; +typedef struct _GstInterSubSrcClass GstInterSubSrcClass; + +struct _GstInterSubSrc +{ + GstBaseSrc base_intersubsrc; + + GstPad *srcpad; + GstInterSurface *surface; + + int rate; + int n_frames; +}; + +struct _GstInterSubSrcClass +{ + GstBaseSrcClass base_intersubsrc_class; +}; + +GType gst_inter_sub_src_get_type (void); + +G_END_DECLS + +#endif diff --git a/gst/inter/gstintersurface.h b/gst/inter/gstintersurface.h index 92440448ad..3e7e10c27e 100644 --- a/gst/inter/gstintersurface.h +++ b/gst/inter/gstintersurface.h @@ -45,6 +45,7 @@ struct _GstInterSurface int n_channels; GstBuffer *video_buffer; + GstBuffer *sub_buffer; GstAdapter *audio_adapter; }; From 70684f4d1ba27a2815f970d8c6810ecc10fb2fd5 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 18 Aug 2011 19:49:08 -0700 Subject: [PATCH 27/57] colorspace: Add jpeg color-matrix conversion --- gst/colorspace/colorspace.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index 15b6caf418..e1f6302757 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -1539,6 +1539,28 @@ matrix_yuv_bt470_6_to_yuv_bt709 (ColorspaceConvert * convert) } } +static void +matrix_yuv_jpeg_to_bt470_6 (ColorspaceConvert * convert) +{ + int i; + int y, u, v; + guint8 *tmpline = convert->tmpline; + + for (i = 0; i < convert->width; i++) { + y = tmpline[i * 4 + 1]; + u = tmpline[i * 4 + 2]; + v = tmpline[i * 4 + 3]; + + y = (220 * y + 16 * 256 + 128) >> 8; + //u = (261 * u + 29 * v - 4367) >> 8; + //v = (19 * u + 262 * v - 3289) >> 8; + + tmpline[i * 4 + 1] = CLAMP (y, 0, 255); + tmpline[i * 4 + 2] = CLAMP (u, 0, 255); + tmpline[i * 4 + 3] = CLAMP (v, 0, 255); + } +} + static void matrix_identity (ColorspaceConvert * convert) { @@ -1750,6 +1772,11 @@ colorspace_convert_lookup_getput (ColorspaceConvert * convert) && convert->to_spec == COLOR_SPEC_YUV_BT709) { convert->matrix = matrix_yuv_bt470_6_to_yuv_bt709; convert->matrix16 = matrix16_yuv_bt470_6_to_yuv_bt709; + } else if (convert->from_spec == COLOR_SPEC_YUV_JPEG + && convert->to_spec == COLOR_SPEC_YUV_BT470_6) { + convert->matrix = matrix_yuv_jpeg_to_bt470_6; + //convert->matrix16 = matrix16_yuv_jpeg_to_bt470_6; + convert->matrix16 = matrix16_identity; } } From f4afa8e53cb8629cbc9021d12f7fe5101201046e Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 31 Dec 2011 17:13:02 -0800 Subject: [PATCH 28/57] avc: fix broken line continuation --- sys/avc/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/avc/Makefile.am b/sys/avc/Makefile.am index 9bde7510b7..963f514941 100644 --- a/sys/avc/Makefile.am +++ b/sys/avc/Makefile.am @@ -6,7 +6,7 @@ libgstavc_la_CPPFLAGS = \ $(GST_PLUGINS_BAD_CXXFLAGS) \ $(GST_PLUGINS_BASE_CXXFLAGS) \ $(GST_CXXFLAGS) \ - -framework AVCVideoServices + -framework AVCVideoServices \ -Wno-deprecated-declarations libgstavc_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) \ From e2abd5c83390032531f4470cc9356119cecb44e6 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 22 Jan 2012 15:48:28 -0800 Subject: [PATCH 29/57] schro: Handle 10 and 16-bit formats --- configure.ac | 2 +- ext/schroedinger/gstschrodec.c | 27 ++++++++++++++++++++------- ext/schroedinger/gstschroenc.c | 27 ++++++++++++++++++++++++--- ext/schroedinger/gstschroutils.c | 23 +++++++++++++++++++++++ ext/schroedinger/gstschroutils.h | 6 ++++++ 5 files changed, 74 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index 9d5d9522c6..a0f0c39358 100644 --- a/configure.ac +++ b/configure.ac @@ -1702,7 +1702,7 @@ AG_GST_CHECK_FEATURE(VDPAU, [VDPAU], vdpau, [ dnl *** schroedinger *** translit(dnm, m, l) AM_CONDITIONAL(USE_SCHRO, true) AG_GST_CHECK_FEATURE(SCHRO, [Schroedinger video codec], schro, [ - AG_GST_PKG_CHECK_MODULES(SCHRO, schroedinger-1.0 >= 1.0.7) + AG_GST_PKG_CHECK_MODULES(SCHRO, schroedinger-1.0 >= 1.0.10) ]) dnl *** zbar *** diff --git a/ext/schroedinger/gstschrodec.c b/ext/schroedinger/gstschrodec.c index bbff0ebe2c..030298e40c 100644 --- a/ext/schroedinger/gstschrodec.c +++ b/ext/schroedinger/gstschrodec.c @@ -102,7 +102,7 @@ static GstStaticPadTemplate gst_schro_dec_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YUY2, AYUV }")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV (GST_SCHRO_YUV_LIST)) ); GST_BOILERPLATE (GstSchroDec, gst_schro_dec, GstBaseVideoDecoder, @@ -313,12 +313,25 @@ parse_sequence_header (GstSchroDec * schro_dec, guint8 * data, int size) ret = schro_parse_decode_sequence_header (data + 13, size - 13, &video_format); if (ret) { - if (video_format.chroma_format == SCHRO_CHROMA_444) { - state->format = GST_VIDEO_FORMAT_AYUV; - } else if (video_format.chroma_format == SCHRO_CHROMA_422) { - state->format = GST_VIDEO_FORMAT_YUY2; - } else if (video_format.chroma_format == SCHRO_CHROMA_420) { - state->format = GST_VIDEO_FORMAT_I420; + int bit_depth; + + bit_depth = schro_video_format_get_bit_depth (&video_format); + + if (bit_depth == 8) { + if (video_format.chroma_format == SCHRO_CHROMA_444) { + state->format = GST_VIDEO_FORMAT_AYUV; + } else if (video_format.chroma_format == SCHRO_CHROMA_422) { + state->format = GST_VIDEO_FORMAT_UYVY; + } else if (video_format.chroma_format == SCHRO_CHROMA_420) { + state->format = GST_VIDEO_FORMAT_I420; + } + } else if (bit_depth <= 10) { + state->format = GST_VIDEO_FORMAT_v210; + } else if (bit_depth <= 16) { + state->format = GST_VIDEO_FORMAT_AYUV64; + } else { + GST_ERROR ("bit depth too large (%d > 16)", bit_depth); + state->format = GST_VIDEO_FORMAT_AYUV64; } state->fps_n = video_format.frame_rate_numerator; state->fps_d = video_format.frame_rate_denominator; diff --git a/ext/schroedinger/gstschroenc.c b/ext/schroedinger/gstschroenc.c index d1eb498fb5..7ed96b3b74 100644 --- a/ext/schroedinger/gstschroenc.c +++ b/ext/schroedinger/gstschroenc.c @@ -107,7 +107,7 @@ static GstStaticPadTemplate gst_schro_enc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, AYUV }")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV (GST_SCHRO_YUV_LIST)) ); static GstStaticPadTemplate gst_schro_enc_src_template = @@ -271,13 +271,18 @@ gst_schro_enc_set_format (GstBaseVideoEncoder * base_video_encoder, switch (state->format) { case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y42B: schro_enc->video_format->chroma_format = SCHRO_CHROMA_420; break; case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_v210: schro_enc->video_format->chroma_format = SCHRO_CHROMA_422; break; case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_AYUV64: schro_enc->video_format->chroma_format = SCHRO_CHROMA_444; break; case GST_VIDEO_FORMAT_ARGB: @@ -300,8 +305,24 @@ gst_schro_enc_set_format (GstBaseVideoEncoder * base_video_encoder, schro_enc->video_format->aspect_ratio_numerator = state->par_n; schro_enc->video_format->aspect_ratio_denominator = state->par_d; - schro_video_format_set_std_signal_range (schro_enc->video_format, - SCHRO_SIGNAL_RANGE_8BIT_VIDEO); + switch (state->format) { + default: + schro_video_format_set_std_signal_range (schro_enc->video_format, + SCHRO_SIGNAL_RANGE_8BIT_VIDEO); + break; + case GST_VIDEO_FORMAT_v210: + schro_video_format_set_std_signal_range (schro_enc->video_format, + SCHRO_SIGNAL_RANGE_10BIT_VIDEO); + break; + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_AYUV64: + schro_enc->video_format->luma_offset = 64 << 8; + schro_enc->video_format->luma_excursion = 219 << 8; + schro_enc->video_format->chroma_offset = 128 << 8; + schro_enc->video_format->chroma_excursion = 224 << 8; + break; + } + schro_video_format_set_std_colour_spec (schro_enc->video_format, SCHRO_COLOUR_SPEC_HDTV); diff --git a/ext/schroedinger/gstschroutils.c b/ext/schroedinger/gstschroutils.c index 66514a3d53..99a22c8a4b 100644 --- a/ext/schroedinger/gstschroutils.c +++ b/ext/schroedinger/gstschroutils.c @@ -72,6 +72,29 @@ gst_schro_buffer_wrap (GstBuffer * buf, GstVideoFormat format, int width, frame = schro_frame_new_from_data_AYUV (GST_BUFFER_DATA (buf), width, height); break; + case GST_VIDEO_FORMAT_Y42B: + frame = + schro_frame_new_from_data_Y42B (GST_BUFFER_DATA (buf), width, height); + break; + case GST_VIDEO_FORMAT_Y444: + frame = + schro_frame_new_from_data_Y444 (GST_BUFFER_DATA (buf), width, height); + break; + case GST_VIDEO_FORMAT_v210: + frame = + schro_frame_new_from_data_v210 (GST_BUFFER_DATA (buf), width, height); + break; + case GST_VIDEO_FORMAT_v216: + frame = + schro_frame_new_from_data_v216 (GST_BUFFER_DATA (buf), width, height); + break; +#ifdef SCHRO_FRAME_FORMAT_AY64 + /* Added in 1.0.11 */ + case GST_VIDEO_FORMAT_AYUV64: + frame = + schro_frame_new_from_data_AY64 (GST_BUFFER_DATA (buf), width, height); + break; +#endif #if 0 case GST_VIDEO_FORMAT_ARGB: { diff --git a/ext/schroedinger/gstschroutils.h b/ext/schroedinger/gstschroutils.h index 4e8ca2de3c..a9924a6331 100644 --- a/ext/schroedinger/gstschroutils.h +++ b/ext/schroedinger/gstschroutils.h @@ -24,6 +24,12 @@ #include #include +#ifdef SCHRO_FRAME_FORMAT_AY64 +#define GST_SCHRO_YUV_LIST "{ I420, YV12, YUY2, UYVY, AYUV, Y42B, Y444, v216, v210, AY64 }" +#else +#define GST_SCHRO_YUV_LIST "{ I420, YV12, YUY2, UYVY, AYUV, Y42B, Y444 }" +#endif + SchroFrame * gst_schro_buffer_wrap (GstBuffer *buf, GstVideoFormat format, int width, int height); From 4eb4602746e6d9ed78b2d822d189a33e099f8836 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 22 Jan 2012 15:49:12 -0800 Subject: [PATCH 30/57] inter: Add channel property --- gst/inter/gstinter.c | 2 -- gst/inter/gstinteraudiosink.c | 7 ++++++- gst/inter/gstinteraudiosrc.c | 7 ++++++- gst/inter/gstintersurface.c | 33 +++++++++++++++++++++++++------ gst/inter/gstintersurface.h | 3 ++- gst/inter/gstintervideosink.c | 33 +++++++++++++++++++++++++++---- gst/inter/gstintervideosink.h | 1 + gst/inter/gstintervideosrc.c | 37 ++++++++++++++++++++++------------- gst/inter/gstintervideosrc.h | 2 ++ 9 files changed, 96 insertions(+), 29 deletions(-) diff --git a/gst/inter/gstinter.c b/gst/inter/gstinter.c index bae82bc0fd..8a7786dbca 100644 --- a/gst/inter/gstinter.c +++ b/gst/inter/gstinter.c @@ -45,8 +45,6 @@ plugin_init (GstPlugin * plugin) gst_element_register (plugin, "intervideosink", GST_RANK_NONE, GST_TYPE_INTER_VIDEO_SINK); - gst_inter_surface_init (); - return TRUE; } diff --git a/gst/inter/gstinteraudiosink.c b/gst/inter/gstinteraudiosink.c index a05248b837..342ebf519f 100644 --- a/gst/inter/gstinteraudiosink.c +++ b/gst/inter/gstinteraudiosink.c @@ -77,7 +77,8 @@ static gboolean gst_inter_audio_sink_unlock_stop (GstBaseSink * sink); enum { - PROP_0 + PROP_0, + PROP_CHANNEL }; /* pad templates */ @@ -150,6 +151,10 @@ gst_inter_audio_sink_class_init (GstInterAudioSinkClass * klass) base_sink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_inter_audio_sink_unlock_stop); + g_object_class_install_property (gobject_class, PROP_CHANNEL, + g_param_spec_string ("channel", "Channel", + "Channel name to match inter src and sink elements", + "default", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void diff --git a/gst/inter/gstinteraudiosrc.c b/gst/inter/gstinteraudiosrc.c index 1b98adc8fc..af9c295b20 100644 --- a/gst/inter/gstinteraudiosrc.c +++ b/gst/inter/gstinteraudiosrc.c @@ -79,7 +79,8 @@ gst_inter_audio_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek, enum { - PROP_0 + PROP_0, + PROP_CHANNEL }; /* pad templates */ @@ -158,6 +159,10 @@ gst_inter_audio_src_class_init (GstInterAudioSrcClass * klass) base_src_class->prepare_seek_segment = GST_DEBUG_FUNCPTR (gst_inter_audio_src_prepare_seek_segment); + g_object_class_install_property (gobject_class, PROP_CHANNEL, + g_param_spec_string ("channel", "Channel", + "Channel name to match inter src and sink elements", + "default", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } diff --git a/gst/inter/gstintersurface.c b/gst/inter/gstintersurface.c index 545cd6ffa2..1d23e5de15 100644 --- a/gst/inter/gstintersurface.c +++ b/gst/inter/gstintersurface.c @@ -21,22 +21,43 @@ #include "config.h" #endif +#include + #include "gstintersurface.h" -static GstInterSurface *surface; +static GList *list; +static GStaticMutex mutex = G_STATIC_MUTEX_INIT; GstInterSurface * gst_inter_surface_get (const char *name) { - return surface; + GList *g; + GstInterSurface *surface; + g_static_mutex_lock (&mutex); + + for (g = list; g; g = g_list_next (g)) { + surface = (GstInterSurface *) g->data; + if (strcmp (name, surface->name) == 0) { + g_static_mutex_unlock (&mutex); + return surface; + } + } + + surface = g_malloc0 (sizeof (GstInterSurface)); + surface->name = g_strdup (name); + surface->mutex = g_mutex_new (); + surface->audio_adapter = gst_adapter_new (); + + list = g_list_append (list, surface); + g_static_mutex_unlock (&mutex); + + return surface; } void -gst_inter_surface_init (void) +gst_inter_surface_unref (GstInterSurface * surface) { - surface = g_malloc0 (sizeof (GstInterSurface)); - surface->mutex = g_mutex_new (); - surface->audio_adapter = gst_adapter_new (); + } diff --git a/gst/inter/gstintersurface.h b/gst/inter/gstintersurface.h index 3e7e10c27e..d8ba11f4c9 100644 --- a/gst/inter/gstintersurface.h +++ b/gst/inter/gstintersurface.h @@ -30,6 +30,7 @@ typedef struct _GstInterSurface GstInterSurface; struct _GstInterSurface { GMutex *mutex; + char *name; /* video */ GstVideoFormat format; @@ -51,7 +52,7 @@ struct _GstInterSurface GstInterSurface * gst_inter_surface_get (const char *name); -void gst_inter_surface_init (void); +void gst_inter_surface_unref (GstInterSurface *surface); G_END_DECLS diff --git a/gst/inter/gstintervideosink.c b/gst/inter/gstintervideosink.c index 43349f9d22..c77328885a 100644 --- a/gst/inter/gstintervideosink.c +++ b/gst/inter/gstintervideosink.c @@ -76,7 +76,8 @@ static gboolean gst_inter_video_sink_unlock_stop (GstBaseSink * sink); enum { - PROP_0 + PROP_0, + PROP_CHANNEL }; /* pad templates */ @@ -144,6 +145,10 @@ gst_inter_video_sink_class_init (GstInterVideoSinkClass * klass) base_sink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_inter_video_sink_unlock_stop); + g_object_class_install_property (gobject_class, PROP_CHANNEL, + g_param_spec_string ("channel", "Channel", + "Channel name to match inter src and sink elements", + "default", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -151,15 +156,25 @@ gst_inter_video_sink_init (GstInterVideoSink * intervideosink, GstInterVideoSinkClass * intervideosink_class) { intervideosink->surface = gst_inter_surface_get ("default"); + + intervideosink->sinkpad = + gst_pad_new_from_static_template (&gst_inter_video_sink_sink_template, + "sink"); + + intervideosink->channel = g_strdup ("default"); } void gst_inter_video_sink_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { - /* GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); */ + GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); switch (property_id) { + case PROP_CHANNEL: + g_free (intervideosink->channel); + intervideosink->channel = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -170,9 +185,12 @@ void gst_inter_video_sink_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { - /* GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); */ + GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); switch (property_id) { + case PROP_CHANNEL: + g_value_set_string (value, intervideosink->channel); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -192,9 +210,10 @@ gst_inter_video_sink_dispose (GObject * object) void gst_inter_video_sink_finalize (GObject * object) { - /* GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); */ + GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); /* clean up object here */ + g_free (intervideosink->channel); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -248,6 +267,9 @@ gst_inter_video_sink_get_times (GstBaseSink * sink, GstBuffer * buffer, static gboolean gst_inter_video_sink_start (GstBaseSink * sink) { + GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (sink); + + intervideosink->surface = gst_inter_surface_get (intervideosink->channel); return TRUE; } @@ -264,6 +286,9 @@ gst_inter_video_sink_stop (GstBaseSink * sink) intervideosink->surface->video_buffer = NULL; g_mutex_unlock (intervideosink->surface->mutex); + gst_inter_surface_unref (intervideosink->surface); + intervideosink->surface = NULL; + return TRUE; } diff --git a/gst/inter/gstintervideosink.h b/gst/inter/gstintervideosink.h index 5b02efe62d..5e421c6d02 100644 --- a/gst/inter/gstintervideosink.h +++ b/gst/inter/gstintervideosink.h @@ -39,6 +39,7 @@ struct _GstInterVideoSink GstBaseSink base_intervideosink; GstInterSurface *surface; + char *channel; int fps_n; int fps_d; diff --git a/gst/inter/gstintervideosrc.c b/gst/inter/gstintervideosrc.c index 2f5dbbac0f..4fa1df8eae 100644 --- a/gst/inter/gstintervideosrc.c +++ b/gst/inter/gstintervideosrc.c @@ -80,7 +80,8 @@ gst_inter_video_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek, enum { - PROP_0 + PROP_0, + PROP_CHANNEL }; /* pad templates */ @@ -156,6 +157,10 @@ gst_inter_video_src_class_init (GstInterVideoSrcClass * klass) base_src_class->prepare_seek_segment = GST_DEBUG_FUNCPTR (gst_inter_video_src_prepare_seek_segment); + g_object_class_install_property (gobject_class, PROP_CHANNEL, + g_param_spec_string ("channel", "Channel", + "Channel name to match inter src and sink elements", + "default", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } @@ -166,16 +171,20 @@ gst_inter_video_src_init (GstInterVideoSrc * intervideosrc, gst_base_src_set_format (GST_BASE_SRC (intervideosrc), GST_FORMAT_TIME); gst_base_src_set_live (GST_BASE_SRC (intervideosrc), TRUE); - intervideosrc->surface = gst_inter_surface_get ("default"); + intervideosrc->channel = g_strdup ("default"); } void gst_inter_video_src_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { - /* GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); */ + GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); switch (property_id) { + case PROP_CHANNEL: + g_free (intervideosrc->channel); + intervideosrc->channel = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -186,9 +195,12 @@ void gst_inter_video_src_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { - /* GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); */ + GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); switch (property_id) { + case PROP_CHANNEL: + g_value_set_string (value, intervideosrc->channel); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -208,9 +220,10 @@ gst_inter_video_src_dispose (GObject * object) void gst_inter_video_src_finalize (GObject * object) { - /* GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); */ + GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); /* clean up object here */ + g_free (intervideosrc->channel); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -279,6 +292,8 @@ gst_inter_video_src_start (GstBaseSrc * src) GST_DEBUG_OBJECT (intervideosrc, "start"); + intervideosrc->surface = gst_inter_surface_get (intervideosrc->channel); + return TRUE; } @@ -289,6 +304,9 @@ gst_inter_video_src_stop (GstBaseSrc * src) GST_DEBUG_OBJECT (intervideosrc, "stop"); + gst_inter_surface_unref (intervideosrc->surface); + intervideosrc->surface = NULL; + return TRUE; } @@ -391,15 +409,6 @@ gst_inter_video_src_create (GstBaseSrc * src, guint64 offset, guint size, intervideosrc->width) * gst_video_format_get_component_height (intervideosrc->format, 1, intervideosrc->height)); - -#if 0 - { - int i; - for (i = 0; i < 10000; i++) { - data[i] = g_random_int () & 0xff; - } - } -#endif } buffer = gst_buffer_make_metadata_writable (buffer); diff --git a/gst/inter/gstintervideosrc.h b/gst/inter/gstintervideosrc.h index e7a3cd045d..100c21489a 100644 --- a/gst/inter/gstintervideosrc.h +++ b/gst/inter/gstintervideosrc.h @@ -41,6 +41,8 @@ struct _GstInterVideoSrc GstInterSurface *surface; + char *channel; + GstVideoFormat format; int fps_n; int fps_d; From e2e6fdcb6b265db201f191952aeed429e85e834e Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 31 Dec 2011 17:14:24 -0800 Subject: [PATCH 31/57] !colorspace: fix odd size problems --- configure.ac | 2 +- gst/colorspace/colorspace.c | 215 ++++++++++++++++++++++------ gst/colorspace/gstcolorspaceorc.orc | 4 +- 3 files changed, 172 insertions(+), 49 deletions(-) diff --git a/configure.ac b/configure.ac index a0f0c39358..69a020ffc5 100644 --- a/configure.ac +++ b/configure.ac @@ -257,7 +257,7 @@ AC_SUBST(EXIF_CFLAGS) AM_CONDITIONAL(USE_EXIF, test "x$HAVE_EXIF" = "xyes") dnl Orc -ORC_CHECK([0.4.11]) +ORC_CHECK([0.4.16]) dnl set license and copyright notice GST_LICENSE="LGPL" diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index e1f6302757..ad7ce2e75e 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -1870,8 +1870,9 @@ convert_I420_YUY2 (ColorspaceConvert * convert, guint8 * dest, /* now handle last line */ if (convert->height & 1) { - getline_I420 (convert, convert->tmpline, src, convert->height - 1); - putline_YUY2 (convert, dest, convert->tmpline, convert->height - 1); + cogorc_convert_I420_YUY2 (FRAME_GET_LINE (dest, 0, i), convert->tmpline, FRAME_GET_LINE (src, 0, i), FRAME_GET_LINE (src, 0, i), /* note i, not i+1 */ + FRAME_GET_LINE (src, 1, i >> 1), + FRAME_GET_LINE (src, 2, i >> 1), (convert->width + 1) / 2); } } @@ -1892,8 +1893,9 @@ convert_I420_UYVY (ColorspaceConvert * convert, guint8 * dest, /* now handle last line */ if (convert->height & 1) { - getline_I420 (convert, convert->tmpline, src, convert->height - 1); - putline_UYVY (convert, dest, convert->tmpline, convert->height - 1); + cogorc_convert_I420_UYVY (FRAME_GET_LINE (dest, 0, i), convert->tmpline, FRAME_GET_LINE (src, 0, i), FRAME_GET_LINE (src, 0, i), /* note i, not i+1 */ + FRAME_GET_LINE (src, 1, i >> 1), + FRAME_GET_LINE (src, 2, i >> 1), (convert->width + 1) / 2); } } @@ -1914,8 +1916,9 @@ convert_I420_AYUV (ColorspaceConvert * convert, guint8 * dest, /* now handle last line */ if (convert->height & 1) { - getline_I420 (convert, convert->tmpline, src, convert->height - 1); - putline_AYUV (convert, dest, convert->tmpline, convert->height - 1); + cogorc_convert_I420_AYUV (FRAME_GET_LINE (dest, 0, i), convert->tmpline, FRAME_GET_LINE (src, 0, i), FRAME_GET_LINE (src, 0, i), /* note i, not i+1 */ + FRAME_GET_LINE (src, 1, i >> 1), + FRAME_GET_LINE (src, 2, i >> 1), convert->width); } } @@ -1949,17 +1952,43 @@ convert_I420_Y444 (ColorspaceConvert * convert, guint8 * dest, cogorc_planar_chroma_420_444 (FRAME_GET_LINE (dest, 1, 0), 2 * convert->dest_stride[1], FRAME_GET_LINE (dest, 1, 1), 2 * convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0), - convert->src_stride[1], (convert->width + 1) / 2, convert->height / 2); + convert->src_stride[1], convert->width / 2, convert->height / 2); cogorc_planar_chroma_420_444 (FRAME_GET_LINE (dest, 2, 0), 2 * convert->dest_stride[2], FRAME_GET_LINE (dest, 2, 1), 2 * convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0), - convert->src_stride[2], (convert->width + 1) / 2, convert->height / 2); + convert->src_stride[2], convert->width / 2, convert->height / 2); + + /* now handle last column */ + if (convert->width & 1) { + int i; + for (i = 0; i < convert->height; i++) { + guint8 *d; + const guint8 *s; + d = FRAME_GET_LINE (dest, 1, i); + s = FRAME_GET_LINE (src, 1, i / 2); + *d = *s; + d = FRAME_GET_LINE (dest, 2, i); + s = FRAME_GET_LINE (src, 2, i / 2); + *d = *s; + } + } /* now handle last line */ if (convert->height & 1) { - getline_I420 (convert, convert->tmpline, src, convert->height - 1); - putline_Y444 (convert, dest, convert->tmpline, convert->height - 1); + int i; + guint8 *d; + const guint8 *s; + d = FRAME_GET_LINE (dest, 1, convert->height - 1); + s = FRAME_GET_LINE (src, 1, (convert->height - 1) / 2); + for (i = 0; i < convert->width; i++) { + d[i] = s[i / 2]; + } + d = FRAME_GET_LINE (dest, 2, convert->height - 1); + s = FRAME_GET_LINE (src, 2, (convert->height - 1) / 2); + for (i = 0; i < convert->width; i++) { + d[i] = s[i / 2]; + } } } @@ -1983,9 +2012,13 @@ convert_YUY2_I420 (ColorspaceConvert * convert, guint8 * dest, } /* now handle last line */ - if (convert->height & 1) { - getline_YUY2 (convert, convert->tmpline, src, convert->height - 1); - putline_I420 (convert, dest, convert->tmpline, convert->height - 1); + if (convert->width & 1) { + cogorc_convert_YUY2_I420 (FRAME_GET_LINE (dest, 0, i), + convert->tmpline, + FRAME_GET_LINE (dest, 1, i >> 1), + FRAME_GET_LINE (dest, 2, i >> 1), + FRAME_GET_LINE (src, 0, i), + FRAME_GET_LINE (src, 0, i), (convert->width + 1) / 2); } } @@ -1995,13 +2028,23 @@ convert_YUY2_AYUV (ColorspaceConvert * convert, guint8 * dest, { cogorc_convert_YUY2_AYUV (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0), - convert->src_stride[0], (convert->width + 1) / 2, - convert->height & 1 ? convert->height - 1 : convert->height); + convert->src_stride[0], convert->width / 2, convert->height); - /* now handle last line */ - if (convert->height & 1) { - getline_YUY2 (convert, convert->tmpline, src, convert->height - 1); - putline_AYUV (convert, dest, convert->tmpline, convert->height - 1); + /* now handle last column */ + if (convert->width & 1) { + int i; + for (i = 0; i < convert->height; i++) { + guint8 *d; + const guint8 *s; + d = FRAME_GET_LINE (dest, 0, i); + s = FRAME_GET_LINE (src, 0, i); + d += (convert->width - 1) * 4; + s += (convert->width / 2 - 1) * 4; + d[0] = 0xff; + d[1] = s[0]; + d[2] = s[1]; + d[3] = s[3]; + } } } @@ -2045,8 +2088,12 @@ convert_UYVY_I420 (ColorspaceConvert * convert, guint8 * dest, /* now handle last line */ if (convert->height & 1) { - getline_UYVY (convert, convert->tmpline, src, convert->height - 1); - putline_I420 (convert, dest, convert->tmpline, convert->height - 1); + cogorc_convert_UYVY_I420 (FRAME_GET_LINE (dest, 0, i), + convert->tmpline, + FRAME_GET_LINE (dest, 1, i >> 1), + FRAME_GET_LINE (dest, 2, i >> 1), + FRAME_GET_LINE (src, 0, i), + FRAME_GET_LINE (src, 0, i), (convert->width + 1) / 2); } } @@ -2056,13 +2103,24 @@ convert_UYVY_AYUV (ColorspaceConvert * convert, guint8 * dest, { cogorc_convert_UYVY_AYUV (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0), - convert->src_stride[0], (convert->width + 1) / 2, - convert->height & 1 ? convert->height - 1 : convert->height); + convert->src_stride[0], convert->width / 2, + convert->width & 1 ? convert->height - 1 : convert->height); - /* now handle last line */ - if (convert->height & 1) { - getline_UYVY (convert, convert->tmpline, src, convert->height - 1); - putline_AYUV (convert, dest, convert->tmpline, convert->height - 1); + /* now handle last column */ + if (convert->width & 1) { + int i; + for (i = 0; i < convert->height; i++) { + guint8 *d; + const guint8 *s; + d = FRAME_GET_LINE (dest, 0, i); + s = FRAME_GET_LINE (src, 0, i); + d += (convert->width - 1) * 4; + s += (convert->width / 2 - 1) * 4; + d[0] = 0xff; + d[1] = s[1]; + d[2] = s[0]; + d[3] = s[2]; + } } } @@ -2136,13 +2194,29 @@ convert_AYUV_Y42B (ColorspaceConvert * convert, guint8 * dest, convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0), convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0), convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0), - convert->src_stride[0], (convert->width + 1) / 2, - convert->height & 1 ? convert->height - 1 : convert->height); + convert->src_stride[0], convert->width / 2, convert->height); - /* now handle last line */ + /* now handle last column */ if (convert->height & 1) { - getline_AYUV (convert, convert->tmpline, src, convert->height - 1); - putline_Y42B (convert, dest, convert->tmpline, convert->height - 1); + int i; + for (i = 0; i < convert->height; i++) { + guint8 *d; + const guint8 *s; + s = FRAME_GET_LINE (src, 0, i); + s += (convert->width - 1) * 4; + + d = FRAME_GET_LINE (dest, 0, i); + d += convert->width - 1; + d[0] = s[1]; + + d = FRAME_GET_LINE (dest, 1, i); + d += convert->width / 2 - 1; + d[0] = s[2]; + + d = FRAME_GET_LINE (dest, 2, i); + d += convert->width / 2 - 1; + d[0] = s[3]; + } } } @@ -2169,19 +2243,38 @@ convert_Y42B_I420 (ColorspaceConvert * convert, guint8 * dest, cogorc_planar_chroma_422_420 (FRAME_GET_LINE (dest, 1, 0), convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0), 2 * convert->src_stride[1], FRAME_GET_LINE (src, 1, 1), - 2 * convert->src_stride[1], (convert->width + 1) / 2, - convert->height / 2); + 2 * convert->src_stride[1], convert->width / 2, + (convert->height + 1) / 2); cogorc_planar_chroma_422_420 (FRAME_GET_LINE (dest, 2, 0), convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0), 2 * convert->src_stride[2], FRAME_GET_LINE (src, 2, 1), - 2 * convert->src_stride[2], (convert->width + 1) / 2, - convert->height / 2); + 2 * convert->src_stride[2], convert->width / 2, + (convert->height + 1) / 2); - /* now handle last line */ - if (convert->height & 1) { - getline_Y42B (convert, convert->tmpline, src, convert->height - 1); - putline_I420 (convert, dest, convert->tmpline, convert->height - 1); + /* now handle last column */ + if (convert->width & 1) { + int i; + for (i = 0; i < (convert->height + 1) / 2; i++) { + guint8 *d; + const guint8 *s1, *s2; + + s1 = FRAME_GET_LINE (src, 1, i * 2); + s2 = FRAME_GET_LINE (src, 1, i * 2 + 1); + d = FRAME_GET_LINE (dest, 1, i); + s1 += convert->width / 2; + s2 += convert->width / 2; + d += convert->width / 2; + d[0] = (s1[0] + s2[0] + 1) / 2; + + s1 = FRAME_GET_LINE (src, 2, i * 2); + s2 = FRAME_GET_LINE (src, 2, i * 2 + 1); + d = FRAME_GET_LINE (dest, 2, i); + s1 += convert->width / 2; + s2 += convert->width / 2; + d += convert->width / 2; + d[0] = (s1[0] + s2[0] + 1) / 2; + } } } @@ -2247,19 +2340,49 @@ convert_Y444_I420 (ColorspaceConvert * convert, guint8 * dest, cogorc_planar_chroma_444_420 (FRAME_GET_LINE (dest, 1, 0), convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0), 2 * convert->src_stride[1], FRAME_GET_LINE (src, 1, 1), - 2 * convert->src_stride[1], (convert->width + 1) / 2, - convert->height / 2); + 2 * convert->src_stride[1], convert->width / 2, convert->height / 2); cogorc_planar_chroma_444_420 (FRAME_GET_LINE (dest, 2, 0), convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0), 2 * convert->src_stride[2], FRAME_GET_LINE (src, 2, 1), - 2 * convert->src_stride[2], (convert->width + 1) / 2, - convert->height / 2); + 2 * convert->src_stride[2], convert->width / 2, convert->height / 2); + + /* now handle last column */ + if (convert->width & 1) { + int i; + for (i = 0; i < (convert->height + 1) / 2; i++) { + guint8 *d; + const guint8 *s1, *s2; + + s1 = FRAME_GET_LINE (src, 1, i * 2); + s2 = FRAME_GET_LINE (src, 1, i * 2 + 1); + d = FRAME_GET_LINE (dest, 1, i); + s1 += convert->width / 2; + s2 += convert->width / 2; + d += convert->width / 2; + d[0] = (s1[0] + s2[0] + 1) / 2; + + s1 = FRAME_GET_LINE (src, 2, i * 2); + s2 = FRAME_GET_LINE (src, 2, i * 2 + 1); + d = FRAME_GET_LINE (dest, 2, i); + s1 += convert->width / 2; + s2 += convert->width / 2; + d += convert->width / 2; + d[0] = (s1[0] + s2[0] + 1) / 2; + } + } /* now handle last line */ if (convert->height & 1) { - getline_Y444 (convert, convert->tmpline, src, convert->height - 1); - putline_I420 (convert, dest, convert->tmpline, convert->height - 1); + int i; + guint8 *d; + const guint8 *s; + s = FRAME_GET_LINE (src, 1, convert->height - 1); + d = FRAME_GET_LINE (dest, 1, convert->height / 2); + for (i = 0; i < convert->width / 2; i++) { + d[i] = (s[i * 2] + s[i * 2 + 1] + 1) / 2; + } + } } diff --git a/gst/colorspace/gstcolorspaceorc.orc b/gst/colorspace/gstcolorspaceorc.orc index 086990e15e..f52af43f2b 100644 --- a/gst/colorspace/gstcolorspaceorc.orc +++ b/gst/colorspace/gstcolorspaceorc.orc @@ -616,7 +616,7 @@ avgub d, s1, s2 .function cogorc_convert_YUY2_AYUV .flags 2d -.dest 8 ayuv guint8 +.dest 8 ayuv align 4 guint8 .source 4 yuy2 guint8 .const 2 c255 0xff .temp 2 yy @@ -632,7 +632,7 @@ x2 mergewl ayuv, ayay, uvuv .function cogorc_convert_UYVY_AYUV .flags 2d -.dest 8 ayuv guint8 +.dest 8 ayuv align 4 guint8 .source 4 uyvy guint8 .const 2 c255 0xff .temp 2 yy From 3b8b87cb6c217b9f0b52cfa3079c4a36afd1c424 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Mon, 9 Jan 2012 21:59:57 -0800 Subject: [PATCH 32/57] colorspace: Fix out-of-bound errors for v210 --- gst/colorspace/colorspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index ad7ce2e75e..c18d331976 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -412,7 +412,7 @@ putline_v210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, int i; guint8 *destline = FRAME_GET_LINE (dest, 0, j); - for (i = 0; i < convert->width + 5; i += 6) { + for (i = 0; i < convert->width; i += 6) { guint32 a0, a1, a2, a3; guint16 y0, y1, y2, y3, y4, y5; guint16 u0, u1, u2; @@ -518,7 +518,7 @@ putline16_v210 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src, int i; guint8 *destline = FRAME_GET_LINE (dest, 0, j); - for (i = 0; i < convert->width + 5; i += 6) { + for (i = 0; i < convert->width; i += 6) { guint32 a0, a1, a2, a3; guint16 y0, y1, y2, y3, y4, y5; guint16 u0, u1, u2; From 96f7c5374f867ef0337c50425a837e4edc0a4d2d Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 22 Jan 2012 16:55:46 -0800 Subject: [PATCH 33/57] inter: Fix compilation Fix up previously botched rebase. --- gst/inter/gstintersubsink.c | 4 ---- gst/inter/gstintervideosink.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/gst/inter/gstintersubsink.c b/gst/inter/gstintersubsink.c index a5738767e3..1328b18a5d 100644 --- a/gst/inter/gstintersubsink.c +++ b/gst/inter/gstintersubsink.c @@ -146,10 +146,6 @@ gst_inter_sub_sink_init (GstInterSubSink * intersubsink, GstInterSubSinkClass * intersubsink_class) { - intersubsink->sinkpad = - gst_pad_new_from_static_template (&gst_inter_sub_sink_sink_template, - "sink"); - intersubsink->surface = gst_inter_surface_get ("default"); intersubsink->fps_n = 1; diff --git a/gst/inter/gstintervideosink.c b/gst/inter/gstintervideosink.c index c77328885a..856a791613 100644 --- a/gst/inter/gstintervideosink.c +++ b/gst/inter/gstintervideosink.c @@ -157,10 +157,6 @@ gst_inter_video_sink_init (GstInterVideoSink * intervideosink, { intervideosink->surface = gst_inter_surface_get ("default"); - intervideosink->sinkpad = - gst_pad_new_from_static_template (&gst_inter_video_sink_sink_template, - "sink"); - intervideosink->channel = g_strdup ("default"); } From de562a194f901bb7d97f02f0210becbe05bffb41 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 22 Jan 2012 16:58:59 -0800 Subject: [PATCH 34/57] Revert "colorspace: Fix out-of-bound errors for v210" This reverts commit 3b8b87cb6c217b9f0b52cfa3079c4a36afd1c424. Untested commit was accidentally pushed. --- gst/colorspace/colorspace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index c18d331976..ad7ce2e75e 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -412,7 +412,7 @@ putline_v210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, int i; guint8 *destline = FRAME_GET_LINE (dest, 0, j); - for (i = 0; i < convert->width; i += 6) { + for (i = 0; i < convert->width + 5; i += 6) { guint32 a0, a1, a2, a3; guint16 y0, y1, y2, y3, y4, y5; guint16 u0, u1, u2; @@ -518,7 +518,7 @@ putline16_v210 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src, int i; guint8 *destline = FRAME_GET_LINE (dest, 0, j); - for (i = 0; i < convert->width; i += 6) { + for (i = 0; i < convert->width + 5; i += 6) { guint32 a0, a1, a2, a3; guint16 y0, y1, y2, y3, y4, y5; guint16 u0, u1, u2; From 4b11ced2eb695a1f0da33f4aa9b3613d4df98cb4 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 22 Jan 2012 16:59:37 -0800 Subject: [PATCH 35/57] Revert "!colorspace: fix odd size problems" This reverts commit e2e6fdcb6b265db201f191952aeed429e85e834e. Untested commit was accidentally pushed. --- configure.ac | 2 +- gst/colorspace/colorspace.c | 215 ++++++---------------------- gst/colorspace/gstcolorspaceorc.orc | 4 +- 3 files changed, 49 insertions(+), 172 deletions(-) diff --git a/configure.ac b/configure.ac index 69a020ffc5..a0f0c39358 100644 --- a/configure.ac +++ b/configure.ac @@ -257,7 +257,7 @@ AC_SUBST(EXIF_CFLAGS) AM_CONDITIONAL(USE_EXIF, test "x$HAVE_EXIF" = "xyes") dnl Orc -ORC_CHECK([0.4.16]) +ORC_CHECK([0.4.11]) dnl set license and copyright notice GST_LICENSE="LGPL" diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index ad7ce2e75e..e1f6302757 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -1870,9 +1870,8 @@ convert_I420_YUY2 (ColorspaceConvert * convert, guint8 * dest, /* now handle last line */ if (convert->height & 1) { - cogorc_convert_I420_YUY2 (FRAME_GET_LINE (dest, 0, i), convert->tmpline, FRAME_GET_LINE (src, 0, i), FRAME_GET_LINE (src, 0, i), /* note i, not i+1 */ - FRAME_GET_LINE (src, 1, i >> 1), - FRAME_GET_LINE (src, 2, i >> 1), (convert->width + 1) / 2); + getline_I420 (convert, convert->tmpline, src, convert->height - 1); + putline_YUY2 (convert, dest, convert->tmpline, convert->height - 1); } } @@ -1893,9 +1892,8 @@ convert_I420_UYVY (ColorspaceConvert * convert, guint8 * dest, /* now handle last line */ if (convert->height & 1) { - cogorc_convert_I420_UYVY (FRAME_GET_LINE (dest, 0, i), convert->tmpline, FRAME_GET_LINE (src, 0, i), FRAME_GET_LINE (src, 0, i), /* note i, not i+1 */ - FRAME_GET_LINE (src, 1, i >> 1), - FRAME_GET_LINE (src, 2, i >> 1), (convert->width + 1) / 2); + getline_I420 (convert, convert->tmpline, src, convert->height - 1); + putline_UYVY (convert, dest, convert->tmpline, convert->height - 1); } } @@ -1916,9 +1914,8 @@ convert_I420_AYUV (ColorspaceConvert * convert, guint8 * dest, /* now handle last line */ if (convert->height & 1) { - cogorc_convert_I420_AYUV (FRAME_GET_LINE (dest, 0, i), convert->tmpline, FRAME_GET_LINE (src, 0, i), FRAME_GET_LINE (src, 0, i), /* note i, not i+1 */ - FRAME_GET_LINE (src, 1, i >> 1), - FRAME_GET_LINE (src, 2, i >> 1), convert->width); + getline_I420 (convert, convert->tmpline, src, convert->height - 1); + putline_AYUV (convert, dest, convert->tmpline, convert->height - 1); } } @@ -1952,43 +1949,17 @@ convert_I420_Y444 (ColorspaceConvert * convert, guint8 * dest, cogorc_planar_chroma_420_444 (FRAME_GET_LINE (dest, 1, 0), 2 * convert->dest_stride[1], FRAME_GET_LINE (dest, 1, 1), 2 * convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0), - convert->src_stride[1], convert->width / 2, convert->height / 2); + convert->src_stride[1], (convert->width + 1) / 2, convert->height / 2); cogorc_planar_chroma_420_444 (FRAME_GET_LINE (dest, 2, 0), 2 * convert->dest_stride[2], FRAME_GET_LINE (dest, 2, 1), 2 * convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0), - convert->src_stride[2], convert->width / 2, convert->height / 2); - - /* now handle last column */ - if (convert->width & 1) { - int i; - for (i = 0; i < convert->height; i++) { - guint8 *d; - const guint8 *s; - d = FRAME_GET_LINE (dest, 1, i); - s = FRAME_GET_LINE (src, 1, i / 2); - *d = *s; - d = FRAME_GET_LINE (dest, 2, i); - s = FRAME_GET_LINE (src, 2, i / 2); - *d = *s; - } - } + convert->src_stride[2], (convert->width + 1) / 2, convert->height / 2); /* now handle last line */ if (convert->height & 1) { - int i; - guint8 *d; - const guint8 *s; - d = FRAME_GET_LINE (dest, 1, convert->height - 1); - s = FRAME_GET_LINE (src, 1, (convert->height - 1) / 2); - for (i = 0; i < convert->width; i++) { - d[i] = s[i / 2]; - } - d = FRAME_GET_LINE (dest, 2, convert->height - 1); - s = FRAME_GET_LINE (src, 2, (convert->height - 1) / 2); - for (i = 0; i < convert->width; i++) { - d[i] = s[i / 2]; - } + getline_I420 (convert, convert->tmpline, src, convert->height - 1); + putline_Y444 (convert, dest, convert->tmpline, convert->height - 1); } } @@ -2012,13 +1983,9 @@ convert_YUY2_I420 (ColorspaceConvert * convert, guint8 * dest, } /* now handle last line */ - if (convert->width & 1) { - cogorc_convert_YUY2_I420 (FRAME_GET_LINE (dest, 0, i), - convert->tmpline, - FRAME_GET_LINE (dest, 1, i >> 1), - FRAME_GET_LINE (dest, 2, i >> 1), - FRAME_GET_LINE (src, 0, i), - FRAME_GET_LINE (src, 0, i), (convert->width + 1) / 2); + if (convert->height & 1) { + getline_YUY2 (convert, convert->tmpline, src, convert->height - 1); + putline_I420 (convert, dest, convert->tmpline, convert->height - 1); } } @@ -2028,23 +1995,13 @@ convert_YUY2_AYUV (ColorspaceConvert * convert, guint8 * dest, { cogorc_convert_YUY2_AYUV (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0), - convert->src_stride[0], convert->width / 2, convert->height); + convert->src_stride[0], (convert->width + 1) / 2, + convert->height & 1 ? convert->height - 1 : convert->height); - /* now handle last column */ - if (convert->width & 1) { - int i; - for (i = 0; i < convert->height; i++) { - guint8 *d; - const guint8 *s; - d = FRAME_GET_LINE (dest, 0, i); - s = FRAME_GET_LINE (src, 0, i); - d += (convert->width - 1) * 4; - s += (convert->width / 2 - 1) * 4; - d[0] = 0xff; - d[1] = s[0]; - d[2] = s[1]; - d[3] = s[3]; - } + /* now handle last line */ + if (convert->height & 1) { + getline_YUY2 (convert, convert->tmpline, src, convert->height - 1); + putline_AYUV (convert, dest, convert->tmpline, convert->height - 1); } } @@ -2088,12 +2045,8 @@ convert_UYVY_I420 (ColorspaceConvert * convert, guint8 * dest, /* now handle last line */ if (convert->height & 1) { - cogorc_convert_UYVY_I420 (FRAME_GET_LINE (dest, 0, i), - convert->tmpline, - FRAME_GET_LINE (dest, 1, i >> 1), - FRAME_GET_LINE (dest, 2, i >> 1), - FRAME_GET_LINE (src, 0, i), - FRAME_GET_LINE (src, 0, i), (convert->width + 1) / 2); + getline_UYVY (convert, convert->tmpline, src, convert->height - 1); + putline_I420 (convert, dest, convert->tmpline, convert->height - 1); } } @@ -2103,24 +2056,13 @@ convert_UYVY_AYUV (ColorspaceConvert * convert, guint8 * dest, { cogorc_convert_UYVY_AYUV (FRAME_GET_LINE (dest, 0, 0), convert->dest_stride[0], FRAME_GET_LINE (src, 0, 0), - convert->src_stride[0], convert->width / 2, - convert->width & 1 ? convert->height - 1 : convert->height); + convert->src_stride[0], (convert->width + 1) / 2, + convert->height & 1 ? convert->height - 1 : convert->height); - /* now handle last column */ - if (convert->width & 1) { - int i; - for (i = 0; i < convert->height; i++) { - guint8 *d; - const guint8 *s; - d = FRAME_GET_LINE (dest, 0, i); - s = FRAME_GET_LINE (src, 0, i); - d += (convert->width - 1) * 4; - s += (convert->width / 2 - 1) * 4; - d[0] = 0xff; - d[1] = s[1]; - d[2] = s[0]; - d[3] = s[2]; - } + /* now handle last line */ + if (convert->height & 1) { + getline_UYVY (convert, convert->tmpline, src, convert->height - 1); + putline_AYUV (convert, dest, convert->tmpline, convert->height - 1); } } @@ -2194,29 +2136,13 @@ convert_AYUV_Y42B (ColorspaceConvert * convert, guint8 * dest, convert->dest_stride[0], FRAME_GET_LINE (dest, 1, 0), convert->dest_stride[1], FRAME_GET_LINE (dest, 2, 0), convert->dest_stride[2], FRAME_GET_LINE (src, 0, 0), - convert->src_stride[0], convert->width / 2, convert->height); + convert->src_stride[0], (convert->width + 1) / 2, + convert->height & 1 ? convert->height - 1 : convert->height); - /* now handle last column */ + /* now handle last line */ if (convert->height & 1) { - int i; - for (i = 0; i < convert->height; i++) { - guint8 *d; - const guint8 *s; - s = FRAME_GET_LINE (src, 0, i); - s += (convert->width - 1) * 4; - - d = FRAME_GET_LINE (dest, 0, i); - d += convert->width - 1; - d[0] = s[1]; - - d = FRAME_GET_LINE (dest, 1, i); - d += convert->width / 2 - 1; - d[0] = s[2]; - - d = FRAME_GET_LINE (dest, 2, i); - d += convert->width / 2 - 1; - d[0] = s[3]; - } + getline_AYUV (convert, convert->tmpline, src, convert->height - 1); + putline_Y42B (convert, dest, convert->tmpline, convert->height - 1); } } @@ -2243,38 +2169,19 @@ convert_Y42B_I420 (ColorspaceConvert * convert, guint8 * dest, cogorc_planar_chroma_422_420 (FRAME_GET_LINE (dest, 1, 0), convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0), 2 * convert->src_stride[1], FRAME_GET_LINE (src, 1, 1), - 2 * convert->src_stride[1], convert->width / 2, - (convert->height + 1) / 2); + 2 * convert->src_stride[1], (convert->width + 1) / 2, + convert->height / 2); cogorc_planar_chroma_422_420 (FRAME_GET_LINE (dest, 2, 0), convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0), 2 * convert->src_stride[2], FRAME_GET_LINE (src, 2, 1), - 2 * convert->src_stride[2], convert->width / 2, - (convert->height + 1) / 2); + 2 * convert->src_stride[2], (convert->width + 1) / 2, + convert->height / 2); - /* now handle last column */ - if (convert->width & 1) { - int i; - for (i = 0; i < (convert->height + 1) / 2; i++) { - guint8 *d; - const guint8 *s1, *s2; - - s1 = FRAME_GET_LINE (src, 1, i * 2); - s2 = FRAME_GET_LINE (src, 1, i * 2 + 1); - d = FRAME_GET_LINE (dest, 1, i); - s1 += convert->width / 2; - s2 += convert->width / 2; - d += convert->width / 2; - d[0] = (s1[0] + s2[0] + 1) / 2; - - s1 = FRAME_GET_LINE (src, 2, i * 2); - s2 = FRAME_GET_LINE (src, 2, i * 2 + 1); - d = FRAME_GET_LINE (dest, 2, i); - s1 += convert->width / 2; - s2 += convert->width / 2; - d += convert->width / 2; - d[0] = (s1[0] + s2[0] + 1) / 2; - } + /* now handle last line */ + if (convert->height & 1) { + getline_Y42B (convert, convert->tmpline, src, convert->height - 1); + putline_I420 (convert, dest, convert->tmpline, convert->height - 1); } } @@ -2340,49 +2247,19 @@ convert_Y444_I420 (ColorspaceConvert * convert, guint8 * dest, cogorc_planar_chroma_444_420 (FRAME_GET_LINE (dest, 1, 0), convert->dest_stride[1], FRAME_GET_LINE (src, 1, 0), 2 * convert->src_stride[1], FRAME_GET_LINE (src, 1, 1), - 2 * convert->src_stride[1], convert->width / 2, convert->height / 2); + 2 * convert->src_stride[1], (convert->width + 1) / 2, + convert->height / 2); cogorc_planar_chroma_444_420 (FRAME_GET_LINE (dest, 2, 0), convert->dest_stride[2], FRAME_GET_LINE (src, 2, 0), 2 * convert->src_stride[2], FRAME_GET_LINE (src, 2, 1), - 2 * convert->src_stride[2], convert->width / 2, convert->height / 2); - - /* now handle last column */ - if (convert->width & 1) { - int i; - for (i = 0; i < (convert->height + 1) / 2; i++) { - guint8 *d; - const guint8 *s1, *s2; - - s1 = FRAME_GET_LINE (src, 1, i * 2); - s2 = FRAME_GET_LINE (src, 1, i * 2 + 1); - d = FRAME_GET_LINE (dest, 1, i); - s1 += convert->width / 2; - s2 += convert->width / 2; - d += convert->width / 2; - d[0] = (s1[0] + s2[0] + 1) / 2; - - s1 = FRAME_GET_LINE (src, 2, i * 2); - s2 = FRAME_GET_LINE (src, 2, i * 2 + 1); - d = FRAME_GET_LINE (dest, 2, i); - s1 += convert->width / 2; - s2 += convert->width / 2; - d += convert->width / 2; - d[0] = (s1[0] + s2[0] + 1) / 2; - } - } + 2 * convert->src_stride[2], (convert->width + 1) / 2, + convert->height / 2); /* now handle last line */ if (convert->height & 1) { - int i; - guint8 *d; - const guint8 *s; - s = FRAME_GET_LINE (src, 1, convert->height - 1); - d = FRAME_GET_LINE (dest, 1, convert->height / 2); - for (i = 0; i < convert->width / 2; i++) { - d[i] = (s[i * 2] + s[i * 2 + 1] + 1) / 2; - } - + getline_Y444 (convert, convert->tmpline, src, convert->height - 1); + putline_I420 (convert, dest, convert->tmpline, convert->height - 1); } } diff --git a/gst/colorspace/gstcolorspaceorc.orc b/gst/colorspace/gstcolorspaceorc.orc index f52af43f2b..086990e15e 100644 --- a/gst/colorspace/gstcolorspaceorc.orc +++ b/gst/colorspace/gstcolorspaceorc.orc @@ -616,7 +616,7 @@ avgub d, s1, s2 .function cogorc_convert_YUY2_AYUV .flags 2d -.dest 8 ayuv align 4 guint8 +.dest 8 ayuv guint8 .source 4 yuy2 guint8 .const 2 c255 0xff .temp 2 yy @@ -632,7 +632,7 @@ x2 mergewl ayuv, ayay, uvuv .function cogorc_convert_UYVY_AYUV .flags 2d -.dest 8 ayuv align 4 guint8 +.dest 8 ayuv guint8 .source 4 uyvy guint8 .const 2 c255 0xff .temp 2 yy From dbad02437c73b4bdb79cac5b8fcc738181db70f0 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 20 Jan 2012 10:42:21 +0000 Subject: [PATCH 36/57] rsnaudiomunge: keep the object ref longer Since we do not get a ref to the pad, I'm not certain it's safe to drop the object and use the pad later, so hold the object ref till we're done with the pad. --- ext/resindvd/rsnaudiomunge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/resindvd/rsnaudiomunge.c b/ext/resindvd/rsnaudiomunge.c index 94cf7b1503..678bd1e2ea 100644 --- a/ext/resindvd/rsnaudiomunge.c +++ b/ext/resindvd/rsnaudiomunge.c @@ -154,9 +154,9 @@ rsn_audiomunge_set_caps (GstPad * pad, GstCaps * caps) g_return_val_if_fail (munge != NULL, FALSE); otherpad = (pad == munge->srcpad) ? munge->sinkpad : munge->srcpad; - gst_object_unref (munge); ret = gst_pad_set_caps (otherpad, caps); + gst_object_unref (munge); return ret; } From 35c96af778507a44ef800f5b110fd6c7b8433a81 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 20 Jan 2012 12:15:20 +0000 Subject: [PATCH 37/57] resindvdbin: fix video/audio mixup in error message --- ext/resindvd/resindvdbin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/resindvd/resindvdbin.c b/ext/resindvd/resindvdbin.c index cbede40ebd..c73af9a7f2 100644 --- a/ext/resindvd/resindvdbin.c +++ b/ext/resindvd/resindvdbin.c @@ -720,7 +720,7 @@ demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin) ("No MPEG video decoder found")); } else { GST_ELEMENT_WARNING (dvdbin, STREAM, CODEC_NOT_FOUND, (NULL), - ("No MPEG video decoder found")); + ("No MPEG audio decoder found")); } } From 27eb76bf45112263452b7b47cecd75022d480835 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 20 Jan 2012 12:25:09 +0000 Subject: [PATCH 38/57] rsndvdsrc: fix leak --- ext/resindvd/resindvdsrc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 499b44fdd5..75cefe8134 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -268,6 +268,7 @@ rsn_dvdsrc_finalize (GObject * object) g_mutex_free (src->dvd_lock); g_mutex_free (src->branch_lock); g_cond_free (src->still_cond); + g_free (src->device); gst_buffer_replace (&src->alloc_buf, NULL); gst_buffer_replace (&src->next_buf, NULL); From 1c0ccc45f458a2a3e9dbe49cc2084fbcb3f10267 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 20 Jan 2012 15:34:27 +0000 Subject: [PATCH 39/57] resindvd: fix preroll on titles with no audio track https://bugzilla.gnome.org/show_bug.cgi?id=599469 --- ext/resindvd/resindvdbin.c | 33 ++++++++++++++++----------------- ext/resindvd/rsndec.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/ext/resindvd/resindvdbin.c b/ext/resindvd/resindvdbin.c index c73af9a7f2..c1a29eb3e0 100644 --- a/ext/resindvd/resindvdbin.c +++ b/ext/resindvd/resindvdbin.c @@ -470,16 +470,25 @@ create_elements (RsnDvdBin * dvdbin) RSN_TYPE_STREAM_SELECTOR, "audioselect", "Audio stream selector")) return FALSE; + if (!try_create_piece (dvdbin, DVD_ELEM_AUD_MUNGE, NULL, + RSN_TYPE_AUDIOMUNGE, "audioearlymunge", "Audio output filter")) + return FALSE; + if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, NULL, RSN_TYPE_AUDIODEC, "auddec", "audio decoder")) return FALSE; - /* rsnaudiomunge goes after the audio decoding to regulate the stream */ - if (!try_create_piece (dvdbin, DVD_ELEM_AUD_MUNGE, NULL, - RSN_TYPE_AUDIOMUNGE, "audiomunge", "Audio output filter")) - return FALSE; + src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "src"); + sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink"); + if (src == NULL || sink == NULL) + goto failed_aud_connect; + if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) + goto failed_aud_connect; + gst_object_unref (sink); + gst_object_unref (src); + src = sink = NULL; - src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src"); + src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "sink"); if (src == NULL || sink == NULL) @@ -490,18 +499,8 @@ create_elements (RsnDvdBin * dvdbin) gst_object_unref (src); src = sink = NULL; - src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "src"); - sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink"); - if (src == NULL || sink == NULL) - goto failed_aud_connect; - if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) - goto failed_aud_connect; - gst_object_unref (sink); - gst_object_unref (src); - src = sink = NULL; - /* ghost audio munge output pad onto bin */ - src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "src"); + src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src"); if (src == NULL) goto failed_aud_ghost; src_templ = gst_static_pad_template_get (&audio_src_template); @@ -701,7 +700,7 @@ demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin) gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "sink%d"); skip_mq = TRUE; - } else if (can_sink_caps (dvdbin->pieces[DVD_ELEM_AUDDEC], caps)) { + } else if (can_sink_caps (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], caps)) { GST_LOG_OBJECT (dvdbin, "Found audio pad w/ caps %" GST_PTR_FORMAT, caps); dest_pad = gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], diff --git a/ext/resindvd/rsndec.c b/ext/resindvd/rsndec.c index 8d7e3806c5..e826640572 100644 --- a/ext/resindvd/rsndec.c +++ b/ext/resindvd/rsndec.c @@ -247,14 +247,44 @@ _get_decoder_factories (gpointer arg) GstPadTemplate *templ = gst_element_class_get_pad_template (klass, "sink"); RsnDecFactoryFilterCtx ctx = { NULL, }; + GstCaps *raw; + gboolean raw_audio; ctx.desired_caps = gst_pad_template_get_caps (templ); + + raw = gst_caps_from_string ("audio/x-raw-float"); + raw_audio = gst_caps_can_intersect (raw, ctx.desired_caps); + if (raw_audio) { + GstCaps *sub = gst_caps_subtract (ctx.desired_caps, raw); + gst_caps_unref (ctx.desired_caps); + ctx.desired_caps = sub; + } + gst_caps_unref (raw); + /* Set decoder caps to empty. Will be filled by the factory_filter */ ctx.decoder_caps = gst_caps_new_empty (); + GST_DEBUG ("Finding factories for caps: %" GST_PTR_FORMAT, ctx.desired_caps); factories = gst_default_registry_feature_filter ( (GstPluginFeatureFilter) rsndec_factory_filter, FALSE, &ctx); + /* If these are audio caps, we add audioconvert, which is not a decoder, + but allows raw audio to go through relatively unmolested - this will + come handy when we have to send placeholder silence to allow preroll + for those DVDs which have titles with no audio track. */ + if (raw_audio) { + GstPluginFeature *feature; + GST_DEBUG ("These are audio caps, adding audioconvert"); + feature = + gst_default_registry_find_feature ("audioconvert", + GST_TYPE_ELEMENT_FACTORY); + if (feature) { + factories = g_list_append (factories, feature); + } else { + GST_WARNING ("Could not find feature audioconvert"); + } + } + factories = g_list_sort (factories, (GCompareFunc) sort_by_ranks); GST_DEBUG ("Available decoder caps %" GST_PTR_FORMAT, ctx.decoder_caps); @@ -343,7 +373,7 @@ static GstStaticPadTemplate audio_sink_template = GST_STATIC_CAPS ("audio/mpeg,mpegversion=(int)1;" "audio/x-private1-lpcm;" "audio/x-private1-ac3;" "audio/ac3;" "audio/x-ac3;" - "audio/x-private1-dts;") + "audio/x-private1-dts; audio/x-raw-float") ); static GstStaticPadTemplate audio_src_template = GST_STATIC_PAD_TEMPLATE ("src", From b5c5fb58a349ae9479fd9f66ec6f54118e47c5df Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 13:54:32 +0100 Subject: [PATCH 40/57] basevideoencoder: fix parameter sanity check --- gst-libs/gst/video/gstbasevideoencoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-libs/gst/video/gstbasevideoencoder.c b/gst-libs/gst/video/gstbasevideoencoder.c index e4fe35f596..e2c730e799 100644 --- a/gst-libs/gst/video/gstbasevideoencoder.c +++ b/gst-libs/gst/video/gstbasevideoencoder.c @@ -1147,7 +1147,7 @@ void gst_base_video_encoder_set_latency (GstBaseVideoEncoder * base_video_encoder, GstClockTime min_latency, GstClockTime max_latency) { - g_return_if_fail (min_latency >= 0); + g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency)); g_return_if_fail (max_latency >= min_latency); GST_OBJECT_LOCK (base_video_encoder); From ae02c7820b8c6b0e2677969fe03bc9687a67089f Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 13:55:33 +0100 Subject: [PATCH 41/57] nuvdemux: check directly for valid buffer ... rather than doing so indirectly in (incomplete) semantic way. --- gst/nuvdemux/gstnuvdemux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/nuvdemux/gstnuvdemux.c b/gst/nuvdemux/gstnuvdemux.c index 86418f0690..bdbaae0159 100644 --- a/gst/nuvdemux/gstnuvdemux.c +++ b/gst/nuvdemux/gstnuvdemux.c @@ -488,7 +488,7 @@ gst_nuv_demux_stream_data (GstNuvDemux * nuv) switch (h->i_type) { case 'V': { - if (h->i_length == 0) + if (!buf) break; GST_BUFFER_OFFSET (buf) = nuv->video_offset; @@ -499,7 +499,7 @@ gst_nuv_demux_stream_data (GstNuvDemux * nuv) } case 'A': { - if (h->i_length == 0) + if (!buf) break; GST_BUFFER_OFFSET (buf) = nuv->audio_offset; From c004a1e4623be673c59dba85e64fe1ce9b539965 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 13:56:02 +0100 Subject: [PATCH 42/57] festival: enhance some error case handling --- gst/festival/gstfestival.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/gst/festival/gstfestival.c b/gst/festival/gstfestival.c index 4c7e241e8c..47b371b43b 100644 --- a/gst/festival/gstfestival.c +++ b/gst/festival/gstfestival.c @@ -297,22 +297,29 @@ gst_festival_chain (GstPad * pad, GstBuffer * buf) GstFlowReturn ret = GST_FLOW_OK; GstFestival *festival; guint8 *p, *ep; + gint f; FILE *fd; festival = GST_FESTIVAL (GST_PAD_PARENT (pad)); GST_LOG_OBJECT (festival, "Got text buffer, %u bytes", GST_BUFFER_SIZE (buf)); - fd = fdopen (dup (festival->info->server_fd), "wb"); + f = dup (festival->info->server_fd); + if (f < 0) + goto fail_open; + fd = fdopen (f, "wb"); + if (fd == NULL) { + close (f); + goto fail_open; + } /* Copy text over to server, escaping any quotes */ fprintf (fd, "(Parameter.set 'Audio_Required_Rate 16000)\n"); fflush (fd); GST_DEBUG_OBJECT (festival, "issued Parameter.set command"); if (read_response (festival) == FALSE) { - ret = GST_FLOW_ERROR; fclose (fd); - goto out; + goto fail_read; } fprintf (fd, "(tts_textall \""); @@ -332,11 +339,25 @@ gst_festival_chain (GstPad * pad, GstBuffer * buf) /* Read back info from server */ if (read_response (festival) == FALSE) - ret = GST_FLOW_ERROR; + goto fail_read; out: gst_buffer_unref (buf); return ret; + + /* ERRORS */ +fail_open: + { + GST_ELEMENT_ERROR (festival, RESOURCE, OPEN_WRITE, (NULL), (NULL)); + ret = GST_FLOW_ERROR; + goto out; + } +fail_read: + { + GST_ELEMENT_ERROR (festival, RESOURCE, READ, (NULL), (NULL)); + ret = GST_FLOW_ERROR; + goto out; + } } static FT_Info * From 6b71ccb552bbebb572bac4a885a29767b286c576 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 13:57:32 +0100 Subject: [PATCH 43/57] mve: ensure best target found --- gst/mve/mvevideoenc16.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gst/mve/mvevideoenc16.c b/gst/mve/mvevideoenc16.c index ec82523dc2..d94e3daca3 100644 --- a/gst/mve/mvevideoenc16.c +++ b/gst/mve/mvevideoenc16.c @@ -285,6 +285,9 @@ mve_quantize (const GstMveMux * mve, const guint16 * src, } } + if (G_UNLIKELY (!best)) + continue; + ++best->hits; best->r_total += r; best->g_total += g; From ccee94e30d24cd12e70a8591c327e1702ed92f10 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 13:58:04 +0100 Subject: [PATCH 44/57] mve: use signed loop variable ... when using it in i >= 0. --- gst/mve/gstmvemux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/mve/gstmvemux.c b/gst/mve/gstmvemux.c index 87165f46fd..fad163b82e 100644 --- a/gst/mve/gstmvemux.c +++ b/gst/mve/gstmvemux.c @@ -337,7 +337,7 @@ static void gst_mve_mux_palette_analyze (GstMveMux * mvemux, const GstBuffer * pal, guint16 * first, guint16 * last) { - guint i; + gint i; guint32 *col1; col1 = (guint32 *) GST_BUFFER_DATA (pal); From c63be1402a532c9e7c7c7aa9b83a1716793d2dd1 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 13:58:57 +0100 Subject: [PATCH 45/57] mpegvideoparse: prevent some fall-through cases --- gst/mpegvideoparse/mpegvideoparse.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/mpegvideoparse/mpegvideoparse.c b/gst/mpegvideoparse/mpegvideoparse.c index c91ed072b4..cc3639cef2 100644 --- a/gst/mpegvideoparse/mpegvideoparse.c +++ b/gst/mpegvideoparse/mpegvideoparse.c @@ -293,16 +293,20 @@ mpegvideoparse_handle_sequence (MpegVideoParse * mpegvideoparse, switch (new_hdr.level) { case 2: level = levels[0]; + break; case 5: level = levels[2]; profile = "4:2:2"; break; case 10: level = levels[0]; + break; case 11: level = levels[1]; + break; case 13: level = levels[2]; + break; case 14: level = levels[3]; profile = "multiview"; From 552f991ba0710c5cb76c8b8f72cd0c757c52c895 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 14:01:02 +0100 Subject: [PATCH 46/57] mpegdemux: avoid some unlikely leaks --- gst/mpegdemux/gstmpegdemux.c | 9 +++++++-- gst/mpegdemux/gstmpegtsdemux.c | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index 7d5b139050..d1f58d0796 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -399,8 +399,13 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type) break; } - if (name == NULL || template == NULL || caps == NULL) - return NULL; + if (name == NULL || template == NULL || caps == NULL) { + if (name) + g_free (name); + if (caps) + gst_caps_unref (caps); + return FALSE; + } stream = g_new0 (GstFluPSStream, 1); stream->id = id; diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 5ee8daeb10..7d75bbeb03 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -829,8 +829,13 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, default: break; } - if (name == NULL || template == NULL || caps == NULL) + if (name == NULL || template == NULL || caps == NULL) { + if (name) + g_free (name); + if (caps) + gst_caps_unref (caps); return FALSE; + } stream->stream_type = stream_type; stream->id = id; From f1810502a72719be3ac5aa20bf0310f203b31987 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 14:05:45 +0100 Subject: [PATCH 47/57] mpegdemux: avoid NULL manipulation if invalid input --- gst/mpegdemux/mpegtsparse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/mpegdemux/mpegtsparse.c b/gst/mpegdemux/mpegtsparse.c index 164321ec4e..273b3edd40 100644 --- a/gst/mpegdemux/mpegtsparse.c +++ b/gst/mpegdemux/mpegtsparse.c @@ -1274,6 +1274,8 @@ mpegts_parse_get_tags_from_sdt (MpegTSParse * parse, GstStructure * sdt_info) * which looks like service-%d */ sid_str = gst_structure_get_name (service); tmp = g_strstr_len (sid_str, -1, "-"); + if (!tmp) + continue; program_number = atoi (++tmp); program = mpegts_parse_get_program (parse, program_number); From b00ed32c5a541b3ae50d772c3ef6d66a4753efcd Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 14:06:54 +0100 Subject: [PATCH 48/57] mpegtsdemux: avoid NULL manipulation if invalid input --- gst/mpegtsdemux/mpegtsbase.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index d8c7073e5b..c63170e1e1 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -1088,6 +1088,8 @@ mpegts_base_get_tags_from_sdt (MpegTSBase * base, GstStructure * sdt_info) * which looks like service-%d */ sid_str = gst_structure_get_name (service); tmp = g_strstr_len (sid_str, -1, "-"); + if (!tmp) + continue; program_number = atoi (++tmp); program = mpegts_base_get_program (base, program_number); From d8fdd3485b30d1e1e18f9d999d17013315613429 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 23 Jan 2012 14:10:43 +0100 Subject: [PATCH 49/57] mpegtsdemux: break out when stream identified --- gst/mpegtsdemux/tsdemux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index c2ebe1700a..0162ab9aee 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -1045,6 +1045,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, name = g_strdup_printf ("private_%04x", bstream->pid); caps = gst_caps_new_simple ("subpicture/x-dvb", NULL); g_free (desc); + break; } /* hack for itv hd (sid 10510, video pid 3401 */ if (program->program_number == 10510 && bstream->pid == 3401) { From cf74b0bc76106d77bea1a346becc158740d4fdd5 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 23 Jan 2012 17:47:45 +0000 Subject: [PATCH 50/57] mpegtsdemux: fix frequent deadlock demuxing MPEG TS A previous patch to add streams early to fix playback of low bitrate streams causes frequent deadlock of a nature I'm at loss how to fix. I'm not certain whether it's a bug in decodebin2, or in that mpegtsdemux patch. Since it causes a major regression, let it be disabled for now. --- gst/mpegdemux/gstmpegtsdemux.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 7d75bbeb03..2c6db7da39 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -1110,6 +1110,10 @@ gst_mpegts_demux_add_all_streams (GstMpegTSDemux * demux, GstClockTime pts) GstPad *srcpad; gboolean all_added = TRUE; + GST_DEBUG_OBJECT (demux, "Adding streams early fixes a wedge in some low " + "bitrate streams, but causes deadlocks - disabled for now"); + return FALSE; + /* When adding a stream, require either a valid base PCR, or a valid PTS */ if (!gst_mpegts_demux_setup_base_pts (demux, pts)) { GST_ERROR ("Can't set base pts"); From 657226d9f0ea27f3923c6af89a24911eefc28f88 Mon Sep 17 00:00:00 2001 From: Jonas Larsson Date: Mon, 23 Jan 2012 18:51:34 +0100 Subject: [PATCH 51/57] codecparsers: read the cbr_flag in h264_parse_hrd_parameters --- gst-libs/gst/codecparsers/gsth264parser.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 45039f780e..d0c6c45e00 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -518,6 +518,7 @@ gst_h264_parse_hrd_parameters (GstH264HRDParams * hrd, NalReader * nr) for (sched_sel_idx = 0; sched_sel_idx <= hrd->cpb_cnt_minus1; sched_sel_idx++) { READ_UE (nr, hrd->bit_rate_value_minus1[sched_sel_idx]); READ_UE (nr, hrd->cpb_size_value_minus1[sched_sel_idx]); + READ_UINT8 (nr, hrd->cbr_flag[sched_sel_idx], 1); } READ_UINT8 (nr, hrd->initial_cpb_removal_delay_length_minus1, 5); From f847f502b4c6f0e4d07b848dbd4d751330fa7e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 23 Jan 2012 18:01:14 +0000 Subject: [PATCH 52/57] REQUIREMENTS: we need librtmp for rtmp support https://bugzilla.gnome.org/show_bug.cgi?id=668521 --- REQUIREMENTS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/REQUIREMENTS b/REQUIREMENTS index ca498fcf2a..601cebb4fa 100644 --- a/REQUIREMENTS +++ b/REQUIREMENTS @@ -63,7 +63,8 @@ libamrwb (for AMR-WB support) (http://www.penguin.cz/~utx/amr) libkate (for Kate support) (http://libkate.googlecode.com/) - +librtmp (for RTMP support) + (http://rtmpdump.mplayerhq.hu/) Optional (debian) packages: =========================== From 9feea330bb94565b219c983fd7b61840044f10b9 Mon Sep 17 00:00:00 2001 From: Jonas Larsson Date: Mon, 23 Jan 2012 18:30:19 +0000 Subject: [PATCH 53/57] h264parse: fix gst_h264_parse_clock_timestamp always failing --- gst-libs/gst/codecparsers/gsth264parser.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index d0c6c45e00..b969650919 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -1056,6 +1056,8 @@ gst_h264_parse_clock_timestamp (GstH264ClockTimestamp * tim, if (time_offset_length > 0) READ_UINT32 (nr, tim->time_offset, time_offset_length); + return TRUE; + error: GST_WARNING ("error parsing \"Clock timestamp\""); return FALSE; From 4a1ce3f8d2d4df8d80650dd53f7b47c436bcdae7 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 23 Jan 2012 22:20:40 +0000 Subject: [PATCH 54/57] resindvd: fix caps refcount error /me bad monkey. --- ext/resindvd/rsndec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/resindvd/rsndec.c b/ext/resindvd/rsndec.c index e826640572..4c2018362d 100644 --- a/ext/resindvd/rsndec.c +++ b/ext/resindvd/rsndec.c @@ -256,8 +256,9 @@ _get_decoder_factories (gpointer arg) raw_audio = gst_caps_can_intersect (raw, ctx.desired_caps); if (raw_audio) { GstCaps *sub = gst_caps_subtract (ctx.desired_caps, raw); - gst_caps_unref (ctx.desired_caps); ctx.desired_caps = sub; + } else { + gst_caps_ref (ctx.desired_caps); } gst_caps_unref (raw); @@ -289,6 +290,7 @@ _get_decoder_factories (gpointer arg) GST_DEBUG ("Available decoder caps %" GST_PTR_FORMAT, ctx.decoder_caps); gst_caps_unref (ctx.decoder_caps); + gst_caps_unref (ctx.desired_caps); return factories; } From 44862ac067d03771fcbcb66594c7c38b4334f1f4 Mon Sep 17 00:00:00 2001 From: "Oleksij Rempel (Alexey Fisher)" Date: Tue, 24 Jan 2012 11:22:46 +0100 Subject: [PATCH 55/57] vp8enc: trace outgoing timestamps add info level prints for outgoing timestamps. Signed-off-by: Oleksij Rempel (Alexey Fisher) --- ext/vp8/gstvp8enc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/vp8/gstvp8enc.c b/ext/vp8/gstvp8enc.c index 5ed11e3a05..b1f06e056a 100644 --- a/ext/vp8/gstvp8enc.c +++ b/ext/vp8/gstvp8enc.c @@ -1192,6 +1192,9 @@ gst_vp8_enc_shape_output (GstBaseVideoEncoder * base_video_encoder, gst_util_uint64_scale (frame->presentation_frame_number + 1, GST_SECOND * state->fps_d, state->fps_n); + GST_LOG_OBJECT (base_video_encoder, "src ts: %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + ret = gst_pad_push (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), buf); if (ret != GST_FLOW_OK) { GST_WARNING_OBJECT (encoder, "flow error %d", ret); From 0961e2f49464f2762228ce24af48a53616e52da0 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Wed, 18 Jan 2012 11:28:26 +0100 Subject: [PATCH 56/57] mpegpsdemux: don't scan for the last PTS if the first wasn't found --- gst/mpegdemux/gstmpegdemux.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index d1f58d0796..ec9b613300 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -2543,13 +2543,16 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux) " in packet starting at %" G_GUINT64_FORMAT, demux->first_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_pts)), offset); - /* scan for last PTS in the stream */ - offset = demux->sink_segment.stop; - gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_PTS, &demux->last_pts); - GST_DEBUG_OBJECT (demux, "Last PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT - " in packet starting at %" G_GUINT64_FORMAT, - demux->last_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_pts)), - offset); + if (demux->first_pts != G_MAXUINT64) { + /* scan for last PTS in the stream */ + offset = demux->sink_segment.stop; + gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_PTS, + &demux->last_pts); + GST_DEBUG_OBJECT (demux, + "Last PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT + " in packet starting at %" G_GUINT64_FORMAT, demux->last_pts, + GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_pts)), offset); + } /* Detect wrong SCR values */ if (demux->first_scr > demux->last_scr) { GST_DEBUG_OBJECT (demux, "Wrong SCR values detected, searching for " From 8fb0beaf00aeae2ef6081d08f0d74d6e655a53da Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Wed, 18 Jan 2012 12:04:52 +0100 Subject: [PATCH 57/57] mpegpsdemux: limit the amount of scanning done on duration queries Limit the amount of data scanned when looking for PTSes in duration queries as a failsafe for kinda broken, potentially large files with sparse or no PTSes. --- gst/mpegdemux/gstmpegdemux.c | 40 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index ec9b613300..ef29208dee 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -60,6 +60,8 @@ #define SEGMENT_THRESHOLD (300*GST_MSECOND) #define VIDEO_SEGMENT_THRESHOLD (500*GST_MSECOND) +#define DURATION_SCAN_LIMIT 4 * 1024 * 1024 + typedef enum { SCAN_SCR, @@ -154,9 +156,9 @@ static GstStateChangeReturn gst_flups_demux_change_state (GstElement * element, GstStateChange transition); static inline gboolean gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, - guint64 * pos, SCAN_MODE mode, guint64 * rts); + guint64 * pos, SCAN_MODE mode, guint64 * rts, gint limit); static inline gboolean gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, - guint64 * pos, SCAN_MODE mode, guint64 * rts); + guint64 * pos, SCAN_MODE mode, guint64 * rts, gint limit); static inline void gst_flups_demux_send_segment_updates (GstFluPSDemux * demux, GstClockTime new_time); @@ -1051,19 +1053,22 @@ gst_flups_demux_do_seek (GstFluPSDemux * demux, GstSegment * seeksegment) MIN (gst_util_uint64_scale (scr - demux->first_scr, scr_rate_n, scr_rate_d), demux->sink_segment.stop); - found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr); + found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr, 0); if (!found) { - found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr); + found = + gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr, 0); } while (found && fscr < scr) { offset++; - found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr); + found = + gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr, 0); } while (found && fscr > scr && offset > 0) { offset--; - found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr); + found = + gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr, 0); } GST_INFO_OBJECT (demux, "doing seek at offset %" G_GUINT64_FORMAT @@ -2382,7 +2387,7 @@ beach: static inline gboolean gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos, - SCAN_MODE mode, guint64 * rts) + SCAN_MODE mode, guint64 * rts, gint limit) { GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buffer = NULL; @@ -2398,6 +2403,9 @@ gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos, if (offset + scan_sz > demux->sink_segment.stop) return FALSE; + if (limit && offset > *pos + limit) + return FALSE; + if (offset + to_read > demux->sink_segment.stop) to_read = demux->sink_segment.stop - offset; @@ -2435,7 +2443,7 @@ gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos, static inline gboolean gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos, - SCAN_MODE mode, guint64 * rts) + SCAN_MODE mode, guint64 * rts, gint limit) { GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buffer = NULL; @@ -2451,6 +2459,9 @@ gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos, if (offset < scan_sz - 1) return FALSE; + if (limit && offset < *pos - limit) + return FALSE; + if (offset > BLOCK_SZ) offset -= BLOCK_SZ; else { @@ -2522,7 +2533,8 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux) /* Scan for notorious SCR and PTS to calculate the duration */ /* scan for first SCR in the stream */ offset = demux->sink_segment.start; - gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &demux->first_scr); + gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &demux->first_scr, + DURATION_SCAN_LIMIT); GST_DEBUG_OBJECT (demux, "First SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT " in packet starting at %" G_GUINT64_FORMAT, demux->first_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)), @@ -2530,7 +2542,8 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux) demux->first_scr_offset = offset; /* scan for last SCR in the stream */ offset = demux->sink_segment.stop; - gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &demux->last_scr); + gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, + &demux->last_scr, 0); GST_DEBUG_OBJECT (demux, "Last SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT " in packet starting at %" G_GUINT64_FORMAT, demux->last_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_scr)), @@ -2538,7 +2551,8 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux) demux->last_scr_offset = offset; /* scan for first PTS in the stream */ offset = demux->sink_segment.start; - gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, &demux->first_pts); + gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, &demux->first_pts, + DURATION_SCAN_LIMIT); GST_DEBUG_OBJECT (demux, "First PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT " in packet starting at %" G_GUINT64_FORMAT, demux->first_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_pts)), @@ -2547,7 +2561,7 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux) /* scan for last PTS in the stream */ offset = demux->sink_segment.stop; gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_PTS, - &demux->last_pts); + &demux->last_pts, DURATION_SCAN_LIMIT); GST_DEBUG_OBJECT (demux, "Last PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT " in packet starting at %" G_GUINT64_FORMAT, demux->last_pts, @@ -2560,7 +2574,7 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux) offset = demux->first_scr_offset; for (i = 0; i < 10; i++) { offset++; - gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &scr); + gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &scr, 0); if (scr < demux->last_scr) { demux->first_scr = scr; demux->first_scr_offset = offset;