diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioencoder.c b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioencoder.c index 60cc6af703..da7f508b04 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioencoder.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioencoder.c @@ -171,6 +171,7 @@ typedef struct _GstAudioEncoderContext /* MT-protected (with LOCK) */ GstClockTime min_latency; GstClockTime max_latency; + gboolean negotiated; GList *headers; gboolean new_headers; @@ -239,6 +240,11 @@ struct _GstAudioEncoderPrivate /* pending serialized sink events, will be sent from finish_frame() */ GList *pending_events; + + /* these are initial events or events that came in while there was nothing + * in the adapter. these events shall be sent after negotiation but before + * we push the following buffer. */ + GList *early_pending_events; }; @@ -499,8 +505,11 @@ gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full) enc->priv->tags_merge_mode = GST_TAG_MERGE_APPEND; enc->priv->tags_changed = FALSE; - g_list_foreach (enc->priv->pending_events, (GFunc) gst_event_unref, NULL); - g_list_free (enc->priv->pending_events); + g_list_free_full (enc->priv->early_pending_events, + (GDestroyNotify) gst_event_unref); + enc->priv->early_pending_events = NULL; + g_list_free_full (enc->priv->pending_events, + (GDestroyNotify) gst_event_unref); enc->priv->pending_events = NULL; } @@ -597,11 +606,31 @@ gst_audio_encoder_push_event (GstAudioEncoder * enc, GstEvent * event) return gst_pad_push_event (enc->srcpad, event); } +static inline void +gst_audio_encoder_push_early_pending_events (GstAudioEncoder * enc) +{ + GstAudioEncoderPrivate *priv = enc->priv; + + if (priv->early_pending_events) { + GList *pending_events, *l; + + pending_events = priv->early_pending_events; + priv->early_pending_events = NULL; + + GST_DEBUG_OBJECT (enc, "Pushing early pending events"); + for (l = pending_events; l; l = l->next) + gst_audio_encoder_push_event (enc, l->data); + g_list_free (pending_events); + } +} + static inline void gst_audio_encoder_push_pending_events (GstAudioEncoder * enc) { GstAudioEncoderPrivate *priv = enc->priv; + gst_audio_encoder_push_early_pending_events (enc); + if (priv->pending_events) { GList *pending_events, *l; @@ -795,9 +824,9 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, if (G_LIKELY (buf)) priv->got_data = TRUE; - gst_audio_encoder_push_pending_events (enc); + gst_audio_encoder_push_early_pending_events (enc); - /* send after pending events, which likely includes segment event */ + /* send after early pending events, which likely includes segment event */ gst_audio_encoder_check_and_push_pending_tags (enc); /* remove corresponding samples from input */ @@ -1013,6 +1042,10 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, ret = gst_pad_push (enc->srcpad, buf); GST_LOG_OBJECT (enc, "buffer pushed: %s", gst_flow_get_name (ret)); + + /* Now push the events that followed after the buffer got into the + * adapter. */ + gst_audio_encoder_push_pending_events (enc); } else { /* merely advance samples, most work for that already done above */ priv->samples += samples; @@ -1578,8 +1611,8 @@ gst_audio_encoder_sink_event_default (GstAudioEncoder * enc, GstEvent * event) /* and follow along with segment */ enc->input_segment = seg; - enc->priv->pending_events = - g_list_append (enc->priv->pending_events, event); + enc->priv->early_pending_events = + g_list_append (enc->priv->early_pending_events, event); GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); res = TRUE; @@ -1696,8 +1729,13 @@ gst_audio_encoder_sink_event_default (GstAudioEncoder * enc, GstEvent * event) gst_pad_event_default (enc->sinkpad, GST_OBJECT_CAST (enc), event); } else { GST_AUDIO_ENCODER_STREAM_LOCK (enc); - enc->priv->pending_events = - g_list_append (enc->priv->pending_events, event); + if (gst_adapter_available (enc->priv->adapter) == 0) { + enc->priv->early_pending_events = + g_list_append (enc->priv->early_pending_events, event); + } else { + enc->priv->pending_events = + g_list_append (enc->priv->pending_events, event); + } GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); res = TRUE; } @@ -2732,10 +2770,10 @@ gst_audio_encoder_negotiate_default (GstAudioEncoder * enc) GST_DEBUG_OBJECT (enc, "Setting srcpad caps %" GST_PTR_FORMAT, caps); - if (enc->priv->pending_events) { + if (enc->priv->early_pending_events) { GList **pending_events, *l; - pending_events = &enc->priv->pending_events; + pending_events = &enc->priv->early_pending_events; GST_DEBUG_OBJECT (enc, "Pushing pending events"); for (l = *pending_events; l;) { @@ -2814,6 +2852,8 @@ gst_audio_encoder_negotiate_unlocked (GstAudioEncoder * enc) if (G_LIKELY (klass->negotiate)) ret = klass->negotiate (enc); + enc->priv->ctx.negotiated = TRUE; + return ret; }