* only available during parsing */
GstVideoCodecFrame *current_frame;
/* events that should apply to the current frame */
+ /* FIXME 2.0: Use a GQueue or similar, see GstVideoCodecFrame::events */
GList *current_frame_events;
/* events that should be pushed before the next frame */
+ /* FIXME 2.0: Use a GQueue or similar, see GstVideoCodecFrame::events */
GList *pending_events;
/* relative offset of input data */
/* relative offset of frame */
guint64 frame_offset;
/* tracking ts and offsets */
- GList *timestamps;
+ GQueue timestamps;
/* last outgoing ts */
GstClockTime last_timestamp_out;
GstClockTime pts_delta;
gboolean reordered_output;
+ /* FIXME: Consider using a GQueue or other better fitting data structure */
/* reverse playback */
/* collect input */
GList *gather;
guint32 system_frame_number;
guint32 decode_frame_number;
- GList *frames; /* Protected with OBJECT_LOCK */
+ GQueue frames; /* Protected with OBJECT_LOCK */
GstVideoCodecState *input_state;
GstVideoCodecState *output_state; /* OBJECT_LOCK and STREAM_LOCK */
gboolean output_state_changed;
decoder->priv->packetized = TRUE;
decoder->priv->needs_format = FALSE;
+ g_queue_init (&decoder->priv->frames);
+ g_queue_init (&decoder->priv->timestamps);
+
/* properties */
decoder->priv->do_qos = DEFAULT_QOS;
GList *l;
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
- for (l = priv->frames; l; l = l->next) {
+ for (l = priv->frames.head; l; l = l->next) {
GstVideoCodecFrame *frame = l->data;
frame->events = _flush_events (decoder->srcpad, frame->events);
ts->duration = GST_BUFFER_DURATION (buffer);
ts->flags = GST_BUFFER_FLAGS (buffer);
- priv->timestamps = g_list_append (priv->timestamps, ts);
+ g_queue_push_tail (&priv->timestamps, ts);
}
static void
*duration = GST_CLOCK_TIME_NONE;
*flags = 0;
- g = decoder->priv->timestamps;
+ g = decoder->priv->timestamps.head;
while (g) {
ts = g->data;
if (ts->offset <= offset) {
+ GList *next = g->next;
#ifndef GST_DISABLE_GST_DEBUG
got_offset = ts->offset;
#endif
*dts = ts->dts;
*duration = ts->duration;
*flags = ts->flags;
- g = g->next;
- decoder->priv->timestamps = g_list_remove (decoder->priv->timestamps, ts);
+ g_queue_delete_link (&decoder->priv->timestamps, g);
+ g = next;
timestamp_free (ts);
} else {
break;
GST_TIME_ARGS (*pts), GST_TIME_ARGS (*dts), *flags, got_offset, offset);
}
+#if !GLIB_CHECK_VERSION(2, 60, 0)
+#define g_queue_clear_full queue_clear_full
+static void
+queue_clear_full (GQueue * queue, GDestroyNotify free_func)
+{
+ gpointer data;
+
+ while ((data = g_queue_pop_head (queue)) != NULL)
+ free_func (data);
+}
+#endif
+
static void
gst_video_decoder_clear_queues (GstVideoDecoder * dec)
{
g_list_free_full (priv->parse_gather,
(GDestroyNotify) gst_video_codec_frame_unref);
priv->parse_gather = NULL;
- g_list_free_full (priv->frames, (GDestroyNotify) gst_video_codec_frame_unref);
- priv->frames = NULL;
+ g_queue_clear_full (&priv->frames,
+ (GDestroyNotify) gst_video_codec_frame_unref);
}
static void
priv->frame_offset = 0;
gst_adapter_clear (priv->input_adapter);
gst_adapter_clear (priv->output_adapter);
- g_list_free_full (priv->timestamps, (GDestroyNotify) timestamp_free);
- priv->timestamps = NULL;
+ g_queue_clear_full (&priv->timestamps, (GDestroyNotify) timestamp_free);
GST_OBJECT_LOCK (decoder);
priv->bytes_out = 0;
#ifndef GST_DISABLE_GST_DEBUG
GST_LOG_OBJECT (decoder, "n %d in %" G_GSIZE_FORMAT " out %" G_GSIZE_FORMAT,
- g_list_length (priv->frames),
+ priv->frames.length,
gst_adapter_available (priv->input_adapter),
gst_adapter_available (priv->output_adapter));
#endif
sync, GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (frame->dts));
/* Push all pending events that arrived before this frame */
- for (l = priv->frames; l; l = l->next) {
+ for (l = priv->frames.head; l; l = l->next) {
GstVideoCodecFrame *tmp = l->data;
if (tmp->events) {
gboolean seen_none = FALSE;
/* some maintenance regardless */
- for (l = priv->frames; l; l = l->next) {
+ for (l = priv->frames.head; l; l = l->next) {
GstVideoCodecFrame *tmp = l->data;
if (!GST_CLOCK_TIME_IS_VALID (tmp->abidata.ABI.ts)) {
/* some more maintenance, ts2 holds PTS */
min_ts = GST_CLOCK_TIME_NONE;
seen_none = FALSE;
- for (l = priv->frames; l; l = l->next) {
+ for (l = priv->frames.head; l; l = l->next) {
GstVideoCodecFrame *tmp = l->data;
if (!GST_CLOCK_TIME_IS_VALID (tmp->abidata.ABI.ts2)) {
/* unref once from the list */
GST_VIDEO_DECODER_STREAM_LOCK (dec);
- link = g_list_find (dec->priv->frames, frame);
+ link = g_queue_find (&dec->priv->frames, frame);
if (link) {
gst_video_codec_frame_unref (frame);
- dec->priv->frames = g_list_delete_link (dec->priv->frames, link);
+ g_queue_delete_link (&dec->priv->frames, link);
}
if (frame->events) {
dec->priv->pending_events =
", dist %d", GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (frame->dts),
frame->distance_from_sync);
- gst_video_codec_frame_ref (frame);
- priv->frames = g_list_append (priv->frames, frame);
+ g_queue_push_tail (&priv->frames, gst_video_codec_frame_ref (frame));
- if (g_list_length (priv->frames) > 10) {
+ if (priv->frames.length > 10) {
GST_DEBUG_OBJECT (decoder, "decoder frame list getting long: %d frames,"
- "possible internal leaking?", g_list_length (priv->frames));
+ "possible internal leaking?", priv->frames.length);
}
frame->deadline =
GstVideoCodecFrame *frame = NULL;
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
- if (decoder->priv->frames)
- frame = gst_video_codec_frame_ref (decoder->priv->frames->data);
+ if (decoder->priv->frames.head)
+ frame = gst_video_codec_frame_ref (decoder->priv->frames.head->data);
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
return (GstVideoCodecFrame *) frame;
GST_DEBUG_OBJECT (decoder, "frame_number : %d", frame_number);
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
- for (g = decoder->priv->frames; g; g = g->next) {
+ for (g = decoder->priv->frames.head; g; g = g->next) {
GstVideoCodecFrame *tmp = g->data;
if (tmp->system_frame_number == frame_number) {
GList *frames;
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
- frames = g_list_copy (decoder->priv->frames);
- g_list_foreach (frames, (GFunc) gst_video_codec_frame_ref, NULL);
+ frames =
+ g_list_copy_deep (decoder->priv->frames.head,
+ (GCopyFunc) gst_video_codec_frame_ref, NULL);
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
return frames;
/* Push all pending pre-caps events of the oldest frame before
* setting caps */
- frame = decoder->priv->frames ? decoder->priv->frames->data : NULL;
+ frame = decoder->priv->frames.head ? decoder->priv->frames.head->data : NULL;
if (frame || decoder->priv->current_frame_events) {
GList **events, *l;
gint64 min_latency;
gint64 max_latency;
+ /* FIXME 2.0: Use a GQueue or similar, see GstVideoCodecFrame::events */
GList *current_frame_events;
GList *headers;
gboolean new_headers; /* Whether new headers were just set */
- GList *force_key_unit; /* List of pending forced keyunits */
+ GQueue force_key_unit; /* List of pending forced keyunits */
guint32 system_frame_number;
- GList *frames; /* Protected with OBJECT_LOCK */
+ GQueue frames; /* Protected with OBJECT_LOCK */
GstVideoCodecState *input_state;
GstVideoCodecState *output_state;
gboolean output_state_changed;
return NULL;
}
+#if !GLIB_CHECK_VERSION(2, 60, 0)
+#define g_queue_clear_full queue_clear_full
+static void
+queue_clear_full (GQueue * queue, GDestroyNotify free_func)
+{
+ gpointer data;
+
+ while ((data = g_queue_pop_head (queue)) != NULL)
+ free_func (data);
+}
+#endif
+
static gboolean
gst_video_encoder_reset (GstVideoEncoder * encoder, gboolean hard)
{
priv->presentation_frame_number = 0;
priv->distance_from_sync = 0;
- g_list_foreach (priv->force_key_unit, (GFunc) forced_key_unit_event_free,
- NULL);
- g_list_free (priv->force_key_unit);
- priv->force_key_unit = NULL;
+ g_queue_clear_full (&priv->force_key_unit,
+ (GDestroyNotify) forced_key_unit_event_free);
priv->drained = TRUE;
} else {
GList *l;
- for (l = priv->frames; l; l = l->next) {
+ for (l = priv->frames.head; l; l = l->next) {
GstVideoCodecFrame *frame = l->data;
frame->events = _flush_events (encoder->srcpad, frame->events);
encoder->priv->current_frame_events);
}
- g_list_foreach (priv->frames, (GFunc) gst_video_codec_frame_unref, NULL);
- g_list_free (priv->frames);
- priv->frames = NULL;
+ g_queue_clear_full (&priv->frames,
+ (GDestroyNotify) gst_video_codec_frame_unref);
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
priv->headers = NULL;
priv->new_headers = FALSE;
+ g_queue_init (&priv->frames);
+ g_queue_init (&priv->force_key_unit);
+
priv->min_latency = 0;
priv->max_latency = 0;
priv->min_pts = GST_CLOCK_TIME_NONE;
GST_OBJECT_LOCK (encoder);
fevt = forced_key_unit_event_new (running_time, all_headers, count);
- encoder->priv->force_key_unit =
- g_list_append (encoder->priv->force_key_unit, fevt);
+ g_queue_push_tail (&encoder->priv->force_key_unit, fevt);
GST_OBJECT_UNLOCK (encoder);
GST_DEBUG_OBJECT (encoder,
GST_OBJECT_LOCK (encoder);
fevt = forced_key_unit_event_new (running_time, all_headers, count);
- encoder->priv->force_key_unit =
- g_list_append (encoder->priv->force_key_unit, fevt);
+ g_queue_push_tail (&encoder->priv->force_key_unit, fevt);
GST_OBJECT_UNLOCK (encoder);
GST_DEBUG_OBJECT (encoder,
GST_CLOCK_TIME_NONE, duration);
GST_OBJECT_LOCK (encoder);
- if (priv->force_key_unit) {
+ if (priv->force_key_unit.head) {
ForcedKeyUnitEvent *fevt = NULL;
GstClockTime running_time;
GList *l;
gst_segment_to_running_time (&encoder->output_segment, GST_FORMAT_TIME,
cstart);
- for (l = priv->force_key_unit; l; l = l->next) {
+ for (l = priv->force_key_unit.head; l; l = l->next) {
ForcedKeyUnitEvent *tmp = l->data;
/* Skip pending keyunits */
}
GST_OBJECT_UNLOCK (encoder);
- gst_video_codec_frame_ref (frame);
- priv->frames = g_list_append (priv->frames, frame);
+ g_queue_push_tail (&priv->frames, gst_video_codec_frame_ref (frame));
/* new data, more finish needed */
priv->drained = FALSE;
/* Push all pending pre-caps events of the oldest frame before
* setting caps */
- frame = encoder->priv->frames ? encoder->priv->frames->data : NULL;
+ frame = encoder->priv->frames.head ? encoder->priv->frames.head->data : NULL;
if (frame || encoder->priv->current_frame_events) {
GList **events, *l;
GList *link;
/* unref once from the list */
- link = g_list_find (enc->priv->frames, frame);
+ link = g_queue_find (&enc->priv->frames, frame);
if (link) {
gst_video_codec_frame_unref (frame);
- enc->priv->frames = g_list_delete_link (enc->priv->frames, link);
+ g_queue_delete_link (&enc->priv->frames, link);
}
/* unref because this function takes ownership */
gst_video_codec_frame_unref (frame);
GList *l;
/* Push all pending events that arrived before this frame */
- for (l = priv->frames; l; l = l->next) {
+ for (l = priv->frames.head; l; l = l->next) {
GstVideoCodecFrame *tmp = l->data;
if (tmp->events) {
gboolean seen_none = FALSE;
/* some maintenance regardless */
- for (l = priv->frames; l; l = l->next) {
+ for (l = priv->frames.head; l; l = l->next) {
GstVideoCodecFrame *tmp = l->data;
if (!GST_CLOCK_TIME_IS_VALID (tmp->abidata.ABI.ts)) {
GstClockTime stream_time, running_time;
GstEvent *ev;
ForcedKeyUnitEvent *fevt = NULL;
- GList *l;
+ GList *l, *fevt_link = NULL;
running_time =
gst_segment_to_running_time (&encoder->output_segment, GST_FORMAT_TIME,
frame->pts);
GST_OBJECT_LOCK (encoder);
- for (l = priv->force_key_unit; l; l = l->next) {
+ for (l = priv->force_key_unit.head; l; l = l->next) {
ForcedKeyUnitEvent *tmp = l->data;
/* Skip non-pending keyunits */
/* Exact match using the frame id */
if (frame->system_frame_number == tmp->frame_id) {
+ fevt_link = l;
fevt = tmp;
break;
}
/* Simple case, keyunit ASAP */
if (tmp->running_time == GST_CLOCK_TIME_NONE) {
+ fevt_link = l;
fevt = tmp;
break;
}
/* Event for before this frame */
if (tmp->running_time <= running_time) {
+ fevt_link = l;
fevt = tmp;
break;
}
}
- if (fevt) {
- priv->force_key_unit = g_list_remove (priv->force_key_unit, fevt);
- }
+ if (fevt_link)
+ g_queue_delete_link (&priv->force_key_unit, fevt_link);
GST_OBJECT_UNLOCK (encoder);
if (fevt) {
priv->processed++;
- if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && priv->force_key_unit)
+ if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && priv->force_key_unit.head)
gst_video_encoder_send_key_unit_unlocked (encoder, frame, &send_headers);
-
if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)
&& frame->abidata.ABI.num_subframes == 0) {
priv->distance_from_sync = 0;
if (ret != GST_FLOW_OK)
goto done;
- if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && priv->force_key_unit)
+ if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && priv->force_key_unit.head)
gst_video_encoder_send_key_unit_unlocked (encoder, frame, &send_headers);
/* Push pending events only for the first subframe ie segment event.
GstVideoCodecFrame *frame = NULL;
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
- if (encoder->priv->frames)
- frame = gst_video_codec_frame_ref (encoder->priv->frames->data);
+ if (encoder->priv->frames.head)
+ frame = gst_video_codec_frame_ref (encoder->priv->frames.head->data);
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
return (GstVideoCodecFrame *) frame;
GST_DEBUG_OBJECT (encoder, "frame_number : %d", frame_number);
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
- for (g = encoder->priv->frames; g; g = g->next) {
+ for (g = encoder->priv->frames.head; g; g = g->next) {
GstVideoCodecFrame *tmp = g->data;
if (tmp->system_frame_number == frame_number) {
GList *frames;
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
- frames = g_list_copy (encoder->priv->frames);
- g_list_foreach (frames, (GFunc) gst_video_codec_frame_ref, NULL);
+ frames =
+ g_list_copy_deep (encoder->priv->frames.head,
+ (GCopyFunc) gst_video_codec_frame_ref, NULL);
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
return frames;