baseparse: increase keyframe awareness

... which is not particular relevant for audio parsing, but more so
in video cases.  In particular, auto-determine if dealing with video (caps).
This commit is contained in:
Mark Nauwelaerts 2010-11-08 19:58:31 +01:00 committed by Tim-Philipp Müller
parent aed933c0ce
commit 4dc486ddc5

View file

@ -235,6 +235,8 @@ struct _GstBaseParsePrivate
GstClockTime next_ts; GstClockTime next_ts;
GstClockTime prev_ts; GstClockTime prev_ts;
GstClockTime frame_duration; GstClockTime frame_duration;
gboolean seen_keyframe;
gboolean is_video;
guint64 framecount; guint64 framecount;
guint64 bytecount; guint64 bytecount;
@ -544,6 +546,7 @@ gst_base_parse_reset (GstBaseParse * parse)
parse->priv->upstream_has_duration = FALSE; parse->priv->upstream_has_duration = FALSE;
parse->priv->idx_interval = 0; parse->priv->idx_interval = 0;
parse->priv->exact_position = TRUE; parse->priv->exact_position = TRUE;
parse->priv->seen_keyframe = FALSE;
parse->priv->last_ts = GST_CLOCK_TIME_NONE; parse->priv->last_ts = GST_CLOCK_TIME_NONE;
parse->priv->last_offset = 0; parse->priv->last_offset = 0;
@ -849,6 +852,7 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
parse->priv->next_ts = next_ts; parse->priv->next_ts = next_ts;
parse->priv->last_ts = GST_CLOCK_TIME_NONE; parse->priv->last_ts = GST_CLOCK_TIME_NONE;
parse->priv->discont = TRUE; parse->priv->discont = TRUE;
parse->priv->seen_keyframe = FALSE;
break; break;
} }
@ -1265,8 +1269,10 @@ gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset,
2, (const GstIndexAssociation *) &associations); 2, (const GstIndexAssociation *) &associations);
GST_OBJECT_UNLOCK (parse); GST_OBJECT_UNLOCK (parse);
if (key) {
parse->priv->index_last_offset = offset; parse->priv->index_last_offset = offset;
parse->priv->index_last_ts = ts; parse->priv->index_last_ts = ts;
}
ret = TRUE; ret = TRUE;
@ -1346,6 +1352,26 @@ gst_base_parse_check_upstream (GstBaseParse * parse)
parse->priv->upstream_has_duration); parse->priv->upstream_has_duration);
} }
/* checks src caps to determine if dealing with audio or video */
/* TODO maybe forego automagic stuff and let subclass configure it ? */
static void
gst_base_parse_check_media (GstBaseParse * parse)
{
GstCaps *caps;
GstStructure *s;
caps = GST_PAD_CAPS (parse->srcpad);
if (G_LIKELY (caps) && (s = gst_caps_get_structure (caps, 0))) {
parse->priv->is_video =
g_str_has_prefix (gst_structure_get_name (s), "video");
} else {
/* historical default */
parse->priv->is_video = FALSE;
}
GST_DEBUG_OBJECT (parse, "media is video == %d", parse->priv->is_video);
}
/** /**
* gst_base_parse_handle_and_push_buffer: * gst_base_parse_handle_and_push_buffer:
* @parse: #GstBaseParse. * @parse: #GstBaseParse.
@ -1576,6 +1602,9 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
parse->priv->pad_mode == GST_ACTIVATE_PULL ? "loop" : "chain"); parse->priv->pad_mode == GST_ACTIVATE_PULL ? "loop" : "chain");
gst_pad_push_event (parse->srcpad, parse->pending_segment); gst_pad_push_event (parse->srcpad, parse->pending_segment);
parse->pending_segment = NULL; parse->pending_segment = NULL;
/* have caps; check identity */
gst_base_parse_check_media (parse);
} }
/* update bitrates and optionally post corresponding tags /* update bitrates and optionally post corresponding tags
@ -1597,6 +1626,9 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
else else
ret = GST_BASE_PARSE_FLOW_CLIP; ret = GST_BASE_PARSE_FLOW_CLIP;
parse->priv->seen_keyframe |= parse->priv->is_video &&
!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
if (ret == GST_BASE_PARSE_FLOW_CLIP) { if (ret == GST_BASE_PARSE_FLOW_CLIP) {
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
@ -1609,8 +1641,13 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
GST_CLOCK_TIME_IS_VALID (parse->segment.start) && GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) + GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) +
parse->priv->lead_in_ts < parse->segment.start) { parse->priv->lead_in_ts < parse->segment.start) {
if (parse->priv->seen_keyframe) {
GST_LOG_OBJECT (parse, "Frame before segment, after keyframe");
ret = GST_FLOW_OK;
} else {
GST_LOG_OBJECT (parse, "Dropped frame, before segment"); GST_LOG_OBJECT (parse, "Dropped frame, before segment");
ret = GST_BASE_PARSE_FLOW_DROPPED; ret = GST_BASE_PARSE_FLOW_DROPPED;
}
} else { } else {
ret = GST_FLOW_OK; ret = GST_FLOW_OK;
} }
@ -3289,6 +3326,7 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
"mark DISCONT, we did a seek to another position"); "mark DISCONT, we did a seek to another position");
parse->priv->offset = seekpos; parse->priv->offset = seekpos;
parse->priv->last_offset = seekpos; parse->priv->last_offset = seekpos;
parse->priv->seen_keyframe = FALSE;
parse->priv->discont = TRUE; parse->priv->discont = TRUE;
parse->priv->next_ts = start_ts; parse->priv->next_ts = start_ts;
parse->priv->last_ts = GST_CLOCK_TIME_NONE; parse->priv->last_ts = GST_CLOCK_TIME_NONE;