From a7f508012c18f762a8bf07e4336929641df22ba3 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Sun, 9 Oct 2011 21:19:32 +0200 Subject: [PATCH] vorbisenc: only push header buffers following initial events --- ext/vorbis/gstvorbisenc.c | 69 +++++++++++++++++++++++++-------------- ext/vorbis/gstvorbisenc.h | 1 + 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/ext/vorbis/gstvorbisenc.c b/ext/vorbis/gstvorbisenc.c index 6aac4ab6f5..b490d1098d 100644 --- a/ext/vorbis/gstvorbisenc.c +++ b/ext/vorbis/gstvorbisenc.c @@ -106,6 +106,8 @@ static GstFlowReturn gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, static GstCaps *gst_vorbis_enc_getcaps (GstAudioEncoder * enc); static gboolean gst_vorbis_enc_sink_event (GstAudioEncoder * enc, GstEvent * event); +static GstFlowReturn gst_vorbis_enc_pre_push (GstAudioEncoder * enc, + GstBuffer ** buffer); static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc); @@ -163,6 +165,7 @@ gst_vorbis_enc_class_init (GstVorbisEncClass * klass) base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vorbis_enc_handle_frame); base_class->getcaps = GST_DEBUG_FUNCPTR (gst_vorbis_enc_getcaps); base_class->event = GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event); + base_class->pre_push = GST_DEBUG_FUNCPTR (gst_vorbis_enc_pre_push); g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE, g_param_spec_int ("max-bitrate", "Maximum Bitrate", @@ -255,6 +258,8 @@ gst_vorbis_enc_stop (GstAudioEncoder * enc) vorbisenc->last_message = NULL; gst_tag_list_free (vorbisenc->tags); vorbisenc->tags = NULL; + g_slist_foreach (vorbisenc->headers, (GFunc) gst_buffer_unref, NULL); + vorbisenc->headers = NULL; return TRUE; } @@ -620,6 +625,8 @@ gst_vorbis_enc_push_header (GstVorbisEnc * vorbisenc, GstBuffer * buffer) "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT, GST_BUFFER_OFFSET_END (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + gst_buffer_set_caps (buffer, + GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc))); return gst_pad_push (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), buffer); } @@ -740,20 +747,16 @@ gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer) gst_buffer_set_caps (buf1, caps); gst_buffer_set_caps (buf2, caps); gst_buffer_set_caps (buf3, caps); + gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (vorbisenc), caps); gst_caps_unref (caps); - /* push out buffers */ - /* push_buffer takes the reference even for failure */ - if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf1)) != GST_FLOW_OK) - goto failed_header_push; - if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf2)) != GST_FLOW_OK) { - buf2 = NULL; - goto failed_header_push; - } - if ((ret = gst_vorbis_enc_push_header (vorbisenc, buf3)) != GST_FLOW_OK) { - buf3 = NULL; - goto failed_header_push; - } + /* store buffers for later pre_push sending */ + g_slist_foreach (vorbisenc->headers, (GFunc) gst_buffer_unref, NULL); + vorbisenc->headers = NULL; + GST_DEBUG_OBJECT (vorbisenc, "storing header buffers"); + vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf3); + vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf2); + vorbisenc->headers = g_slist_prepend (vorbisenc->headers, buf1); vorbisenc->header_sent = TRUE; } @@ -785,18 +788,6 @@ gst_vorbis_enc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer) ret = gst_vorbis_enc_output_buffers (vorbisenc); return ret; - - /* error cases */ -failed_header_push: - { - GST_WARNING_OBJECT (vorbisenc, "Failed to push headers"); - /* buf1 is always already unreffed */ - if (buf2) - gst_buffer_unref (buf2); - if (buf3) - gst_buffer_unref (buf3); - return ret; - } } static GstFlowReturn @@ -836,6 +827,36 @@ gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc) return GST_FLOW_OK; } +static GstFlowReturn +gst_vorbis_enc_pre_push (GstAudioEncoder * enc, GstBuffer ** buffer) +{ + GstVorbisEnc *vorbisenc; + GstFlowReturn ret = GST_FLOW_OK; + + vorbisenc = GST_VORBISENC (enc); + + /* FIXME 0.11 ? get rid of this special ogg stuff and have it + * put and use 'codec data' in caps like anything else, + * with all the usual out-of-band advantage etc */ + if (G_UNLIKELY (vorbisenc->headers)) { + GSList *header = vorbisenc->headers; + + /* try to push all of these, if we lose one, might as well lose all */ + while (header) { + if (ret == GST_FLOW_OK) + ret = gst_vorbis_enc_push_header (vorbisenc, header->data); + else + gst_vorbis_enc_push_header (vorbisenc, header->data); + header = g_slist_next (header); + } + + g_slist_free (vorbisenc->headers); + vorbisenc->headers = NULL; + } + + return ret; +} + static void gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) diff --git a/ext/vorbis/gstvorbisenc.h b/ext/vorbis/gstvorbisenc.h index 18d1e55f83..ffc60e67ef 100644 --- a/ext/vorbis/gstvorbisenc.h +++ b/ext/vorbis/gstvorbisenc.h @@ -81,6 +81,7 @@ struct _GstVorbisEnc { gboolean setup; gboolean header_sent; gchar *last_message; + GSList *headers; }; struct _GstVorbisEncClass {