/* if the first pad doesn't contain anything or is even NULL, return
* the second pad as best candidate and vice versa */
- if (first == NULL || (first->buffer == NULL && first->next_buffer == NULL))
+ if (first == NULL)
return 1;
- if (second == NULL || (second->buffer == NULL && second->next_buffer == NULL))
+ if (second == NULL)
return -1;
/* no timestamp on first buffer, it must go first */
- if (first->buffer)
- firsttime = GST_BUFFER_TIMESTAMP (first->buffer);
- else
- firsttime = GST_BUFFER_TIMESTAMP (first->next_buffer);
+ firsttime = GST_BUFFER_TIMESTAMP (first->buffer);
if (firsttime == GST_CLOCK_TIME_NONE)
return -1;
/* no timestamp on second buffer, it must go first */
- if (second->buffer)
- secondtime = GST_BUFFER_TIMESTAMP (second->buffer);
- else
- secondtime = GST_BUFFER_TIMESTAMP (second->next_buffer);
+ secondtime = GST_BUFFER_TIMESTAMP (second->buffer);
if (secondtime == GST_CLOCK_TIME_NONE)
return 1;
*
* returns a pointer to an oggpad that holds the best buffer, or
* NULL when no pad was usable. "best" means the buffer marked
- * with the lowest timestamp. If best->buffer == NULL then nothing
- * should be done until more data arrives */
+ * with the lowest timestamp. If best->buffer == NULL then either
+ * we're at EOS (popped = FALSE), or a buffer got dropped, so retry. */
static GstOggPadData *
-gst_ogg_mux_queue_pads (GstOggMux * ogg_mux)
+gst_ogg_mux_queue_pads (GstOggMux * ogg_mux, gboolean * popped)
{
- GstOggPadData *bestpad = NULL, *still_hungry = NULL;
+ GstOggPadData *bestpad = NULL;
GSList *walk;
+ *popped = FALSE;
+
/* try to make sure we have a buffer from each usable pad first */
walk = ogg_mux->collect->data;
while (walk) {
if (pad->buffer == NULL) {
GstBuffer *buf;
- /* shift the buffer along if needed (it's okay if next_buffer is NULL) */
- if (pad->buffer == NULL) {
- GST_LOG_OBJECT (data->pad, "shifting buffer %" GST_PTR_FORMAT,
- pad->next_buffer);
- pad->buffer = pad->next_buffer;
- pad->next_buffer = NULL;
- }
-
buf = gst_collect_pads_pop (ogg_mux->collect, data);
GST_LOG_OBJECT (data->pad, "popped buffer %" GST_PTR_FORMAT, buf);
/* On EOS we get a NULL buffer */
if (buf != NULL) {
+ *popped = TRUE;
+
if (ogg_mux->delta_pad == NULL &&
GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT))
ogg_mux->delta_pad = pad;
if (G_UNLIKELY (!buf))
GST_DEBUG_OBJECT (data->pad, "buffer clipped");
}
- } else {
- GST_DEBUG_OBJECT (data->pad, "EOS on pad");
- if (!pad->eos) {
- ogg_page page;
-
- /* it's no longer active */
- ogg_mux->active_pads--;
-
- /* Just gone to EOS. Flush existing page(s) */
- pad->eos = TRUE;
-
- while (ogg_stream_flush (&pad->map.stream, &page)) {
- /* Place page into the per-pad queue */
- gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page, pad->first_delta);
- /* increment the page number counter */
- pad->pageno++;
- /* mark other pages as delta */
- pad->first_delta = TRUE;
- }
- }
}
- pad->next_buffer = buf;
+ pad->buffer = buf;
}
/* we should have a buffer now, see if it is the best pad to
* pull on */
- if (pad->buffer || pad->next_buffer) {
+ if (pad->buffer) {
if (gst_ogg_mux_compare_pads (ogg_mux, bestpad, pad) > 0) {
GST_LOG_OBJECT (data->pad,
- "new best pad, with buffers %" GST_PTR_FORMAT
- " and %" GST_PTR_FORMAT, pad->buffer, pad->next_buffer);
+ "new best pad, with buffer %" GST_PTR_FORMAT, pad->buffer);
bestpad = pad;
}
- } else if (!pad->eos) {
- GST_LOG_OBJECT (data->pad, "hungry pad");
- still_hungry = pad;
}
}
- if (still_hungry)
- /* drop back into collectpads... */
- return still_hungry;
- else
- return bestpad;
+ return bestpad;
}
static GList *
pad->always_flush_page = TRUE;
} else if (gst_structure_has_name (structure, "video/x-dirac")) {
res = g_list_append (res, pad->buffer);
- pad->buffer = pad->next_buffer;
- pad->next_buffer = NULL;
+ pad->buffer = NULL;
pad->always_flush_page = TRUE;
} else {
GST_LOG_OBJECT (thepad, "caps don't have streamheader");
GST_LOG_OBJECT (mux, "looking at pad %s:%s", GST_DEBUG_PAD_NAME (thepad));
/* if the pad has no buffer, we don't care */
- if (pad->buffer == NULL && pad->next_buffer == NULL)
+ if (pad->buffer == NULL)
continue;
/* now figure out the headers */
} else if (pad->buffer) {
buf = pad->buffer;
gst_buffer_ref (buf);
- } else if (pad->next_buffer) {
- buf = pad->next_buffer;
- gst_buffer_ref (buf);
} else {
/* fixme -- should be caught in the previous list traversal. */
GST_OBJECT_LOCK (thepad);
gboolean delta_unit;
gint64 granulepos = 0;
GstClockTime timestamp, gp_time;
+ GstBuffer *next_buf;
GST_LOG_OBJECT (ogg_mux, "best pad %" GST_PTR_FORMAT
", currently pulling from %" GST_PTR_FORMAT, best->collect.pad,
ogg_mux->pulling);
- /* best->buffer is non-NULL, either the pad is EOS's or there is a next
- * buffer */
- if (best->next_buffer == NULL && !best->eos) {
- GST_WARNING_OBJECT (ogg_mux, "no subsequent buffer and EOS not reached");
- return GST_FLOW_WRONG_STATE;
+ next_buf = gst_collect_pads_peek (ogg_mux->collect, &best->collect);
+ if (next_buf) {
+ best->eos = FALSE;
+ gst_buffer_unref (next_buf);
+ } else {
+ best->eos = TRUE;
}
/* if we were already pulling from one pad, but the new "best" buffer is
GST_GP_CAST (packet.granulepos), (gint64) packet.packetno,
packet.bytes);
- packet.e_o_s = (pad->eos ? 1 : 0);
+ packet.e_o_s = best->eos ? 1 : 0;
tmpbuf = NULL;
/* we flush when we see a new keyframe */
all_pads_eos (GstCollectPads * pads)
{
GSList *walk;
- gboolean alleos = TRUE;
walk = pads->data;
while (walk) {
- GstBuffer *buf;
- GstCollectData *data = (GstCollectData *) walk->data;
+ GstOggPadData *oggpad = (GstOggPadData *) walk->data;
- buf = gst_collect_pads_peek (pads, data);
- if (buf) {
- alleos = FALSE;
- gst_buffer_unref (buf);
- goto beach;
- }
- walk = walk->next;
+ GST_DEBUG ("oggpad %p eos %d", oggpad, oggpad->eos);
+
+ if (oggpad->eos == FALSE)
+ return FALSE;
+
+ walk = g_slist_next (walk);
}
-beach:
- return alleos;
+
+ return TRUE;
}
/* This function is called when there is data on all pads.
{
GstOggPadData *best;
GstFlowReturn ret;
- gint activebefore;
+ gboolean popped;
GST_LOG_OBJECT (ogg_mux, "collected");
- activebefore = ogg_mux->active_pads;
-
/* queue buffers on all pads; find a buffer with the lowest timestamp */
- best = gst_ogg_mux_queue_pads (ogg_mux);
- if (best && !best->buffer) {
- GST_DEBUG_OBJECT (ogg_mux, "No buffer available on best pad");
+ best = gst_ogg_mux_queue_pads (ogg_mux, &popped);
+
+ if (popped)
return GST_FLOW_OK;
- }
- if (!best) {
- return GST_FLOW_WRONG_STATE;
+ if (best == NULL || best->buffer == NULL) {
+ /* This is not supposed to happen */
+ return GST_FLOW_ERROR;
}
ret = gst_ogg_mux_process_best_pad (ogg_mux, best);
- if (ogg_mux->active_pads < activebefore) {
- /* If the active pad count went down, this mean at least one pad has gone
- * EOS. Since CollectPads only calls _collected() once when all pads are
- * EOS, and our code doesn't _pop() from all pads we need to check that by
- * peeking on all pads, else we won't be called again and the muxing will
- * not terminate (push out EOS). */
-
- /* if all the pads have been removed, flush all pending data */
- if ((ret == GST_FLOW_OK) && all_pads_eos (pads)) {
- GST_LOG_OBJECT (ogg_mux, "no pads remaining, flushing data");
-
- do {
- best = gst_ogg_mux_queue_pads (ogg_mux);
- if (best)
- ret = gst_ogg_mux_process_best_pad (ogg_mux, best);
- } while ((ret == GST_FLOW_OK) && (best != NULL));
-
- GST_DEBUG_OBJECT (ogg_mux, "Pushing EOS");
- gst_pad_push_event (ogg_mux->srcpad, gst_event_new_eos ());
- }
+ if (best->eos && all_pads_eos (pads)) {
+ gst_pad_push_event (ogg_mux->srcpad, gst_event_new_eos ());
+ return GST_FLOW_UNEXPECTED;
}
return ret;
gst_buffer_unref (oggpad->buffer);
oggpad->buffer = NULL;
}
- if (oggpad->next_buffer) {
- gst_buffer_unref (oggpad->next_buffer);
- oggpad->next_buffer = NULL;
- }
gst_segment_init (&oggpad->segment, GST_FORMAT_TIME);
}