static gboolean gst_flv_demux_src_event (GstPad * pad, GstObject * parent,
GstEvent * event);
+static GstIndex *gst_flv_demux_get_index (GstElement * element);
static void
gst_flv_demux_parse_and_add_index_entry (GstFlvDemux * demux, GstClockTime ts,
guint64 pos, gboolean keyframe)
{
- static GstIndexAssociation associations[2];
- static GstIndexEntry *entry;
+ GstIndexAssociation associations[2];
+ GstIndex *index;
+ GstIndexEntry *entry;
GST_LOG_OBJECT (demux,
"adding key=%d association %" GST_TIME_FORMAT "-> %" G_GUINT64_FORMAT,
if (!demux->upstream_seekable)
return;
+ index = gst_flv_demux_get_index (GST_ELEMENT (demux));
+
+ if (!index)
+ return;
+
/* entry may already have been added before, avoid adding indefinitely */
- entry = gst_index_get_assoc_entry (demux->index, demux->index_id,
+ entry = gst_index_get_assoc_entry (index, demux->index_id,
GST_INDEX_LOOKUP_EXACT, GST_ASSOCIATION_FLAG_NONE, GST_FORMAT_BYTES, pos);
if (entry) {
if (time != ts || key != ! !keyframe)
GST_DEBUG_OBJECT (demux, "metadata mismatch");
#endif
+ gst_object_unref (index);
return;
}
associations[1].format = GST_FORMAT_BYTES;
associations[1].value = pos;
- gst_index_add_associationv (demux->index, demux->index_id,
+ gst_index_add_associationv (index, demux->index_id,
(keyframe) ? GST_ASSOCIATION_FLAG_KEY_UNIT :
GST_ASSOCIATION_FLAG_DELTA_UNIT, 2,
(const GstIndexAssociation *) &associations);
demux->index_max_pos = pos;
if (ts > demux->index_max_time)
demux->index_max_time = ts;
+
+ gst_object_unref (index);
}
static gchar *
gst_buffer_map (buffer, &map, GST_MAP_READ);
gst_byte_reader_init (&reader, map.data, map.size);
- gst_byte_reader_skip (&reader, 7);
+ gst_byte_reader_skip_unchecked (&reader, 7);
GST_LOG_OBJECT (demux, "parsing a script tag");
g_free (function_name);
- if (demux->index && demux->times && demux->filepositions) {
+ if (demux->times && demux->filepositions) {
guint num;
/* If an index was found, insert associations */
demux->audio_codec_data, NULL);
}
+ gst_pad_push_event (demux->audio_pad, gst_event_new_stream_start ());
ret = gst_pad_set_caps (demux->audio_pad, caps);
if (G_LIKELY (ret)) {
if (demux->taglist) {
GST_DEBUG_OBJECT (demux, "pushing tags out %" GST_PTR_FORMAT,
demux->taglist);
- gst_flv_demux_push_src_event (demux, gst_event_new_tag (demux->taglist));
+ gst_flv_demux_push_src_event (demux, gst_event_new_tag ("GstDemuxer",
+ demux->taglist));
demux->taglist = gst_tag_list_new_empty ();
demux->push_tags = FALSE;
}
/* Only add audio frames to the index if we have no video,
* and if the index is not yet complete */
- if (!demux->has_video && demux->index && !demux->indexed) {
+ if (!demux->has_video && !demux->indexed) {
gst_flv_demux_parse_and_add_index_entry (demux,
GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, TRUE);
}
demux->video_codec_data, NULL);
}
+ gst_pad_push_event (demux->video_pad, gst_event_new_stream_start ());
ret = gst_pad_set_caps (demux->video_pad, caps);
if (G_LIKELY (ret)) {
if (!keyframe)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
- if (!demux->indexed && demux->index) {
+ if (!demux->indexed) {
gst_flv_demux_parse_and_add_index_entry (demux,
GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, keyframe);
}
ret = pts * GST_MSECOND;
GST_LOG_OBJECT (demux, "pts: %" GST_TIME_FORMAT, GST_TIME_ARGS (ret));
- if (index && demux->index && !demux->indexed && (type == 9 || (type == 8
+ if (index && !demux->indexed && (type == 9 || (type == 8
&& !demux->has_video))) {
gst_flv_demux_parse_and_add_index_entry (demux, ret, demux->offset,
keyframe);
demux->offset += FLV_TAG_TYPE_SIZE;
/* Pull the whole tag */
+ buffer = NULL;
if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
demux->tag_size, &buffer)) != GST_FLOW_OK))
goto beach;
gst_flv_demux_seek_to_prev_keyframe (GstFlvDemux * demux)
{
GstFlowReturn ret = GST_FLOW_EOS;
+ GstIndex *index;
GstIndexEntry *entry = NULL;
GST_DEBUG_OBJECT (demux,
GST_DEBUG_OBJECT (demux, "locating previous position");
+ index = gst_flv_demux_get_index (GST_ELEMENT (demux));
+
/* locate index entry before previous start position */
- if (demux->index)
- entry = gst_index_get_assoc_entry (demux->index, demux->index_id,
+ if (index) {
+ entry = gst_index_get_assoc_entry (index, demux->index_id,
GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
GST_FORMAT_BYTES, demux->from_offset - 1);
- if (entry) {
- gint64 bytes = 0, time = 0;
+ if (entry) {
+ gint64 bytes = 0, time = 0;
- gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
- gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
+ gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
+ gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
- GST_DEBUG_OBJECT (demux, "found index entry for %" G_GINT64_FORMAT
- " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
- demux->offset - 1, GST_TIME_ARGS (time), bytes);
+ GST_DEBUG_OBJECT (demux, "found index entry for %" G_GINT64_FORMAT
+ " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
+ demux->offset - 1, GST_TIME_ARGS (time), bytes);
- /* setup for next section */
- demux->to_offset = demux->from_offset;
- gst_flv_demux_move_to_offset (demux, bytes, FALSE);
- ret = GST_FLOW_OK;
+ /* setup for next section */
+ demux->to_offset = demux->from_offset;
+ gst_flv_demux_move_to_offset (demux, bytes, FALSE);
+ ret = GST_FLOW_OK;
+ }
+
+ gst_object_unref (index);
}
+
done:
return ret;
}
old_offset = demux->offset;
demux->offset = pos;
+ buffer = NULL;
while ((ret = gst_flv_demux_pull_range (demux, demux->sinkpad, demux->offset,
12, &buffer)) == GST_FLOW_OK) {
tag_time =
gst_flv_demux_parse_tag_timestamp (demux, TRUE, buffer, &tag_size);
gst_buffer_unref (buffer);
+ buffer = NULL;
if (G_UNLIKELY (tag_time == GST_CLOCK_TIME_NONE || tag_time > ts))
goto exit;
gst_element_post_message (GST_ELEMENT_CAST (demux),
gst_message_new_segment_done (GST_OBJECT_CAST (demux),
GST_FORMAT_TIME, stop));
+ gst_flv_demux_push_src_event (demux,
+ gst_event_new_segment_done (GST_FORMAT_TIME, stop));
} else { /* Reverse playback */
GST_LOG_OBJECT (demux, "Sending segment done, at beginning of "
"segment");
gst_element_post_message (GST_ELEMENT_CAST (demux),
gst_message_new_segment_done (GST_OBJECT_CAST (demux),
GST_FORMAT_TIME, demux->segment.start));
+ gst_flv_demux_push_src_event (demux,
+ gst_event_new_segment_done (GST_FORMAT_TIME,
+ demux->segment.start));
}
} else {
/* normal playback, send EOS to all linked pads */
}
GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
- if (!gst_flv_demux_push_src_event (demux, gst_event_new_eos ()))
+ if (!demux->audio_pad && !demux->video_pad)
+ GST_ELEMENT_ERROR (demux, STREAM, FAILED,
+ ("Internal data stream error."), ("Got EOS before any data"));
+ else if (!gst_flv_demux_push_src_event (demux, gst_event_new_eos ()))
GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
}
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
{
gint64 bytes = 0;
gint64 time = 0;
+ GstIndex *index;
GstIndexEntry *entry;
g_return_val_if_fail (segment != NULL, 0);
time = segment->position;
- if (demux->index) {
+ index = gst_flv_demux_get_index (GST_ELEMENT (demux));
+
+ if (index) {
/* Let's check if we have an index entry for that seek time */
- entry = gst_index_get_assoc_entry (demux->index, demux->index_id,
+ entry = gst_index_get_assoc_entry (index, demux->index_id,
GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
GST_FORMAT_TIME, time);
GST_DEBUG_OBJECT (demux, "no index entry found for %" GST_TIME_FORMAT,
GST_TIME_ARGS (segment->start));
}
+
+ gst_object_unref (index);
}
return bytes;
gst_pad_pause_task (demux->sinkpad);
} else {
gst_pad_start_task (demux->sinkpad,
- (GstTaskFunction) gst_flv_demux_loop, demux->sinkpad);
+ (GstTaskFunction) gst_flv_demux_loop, demux->sinkpad, NULL);
}
GST_PAD_STREAM_UNLOCK (demux->sinkpad);
if (active) {
demux->random_access = TRUE;
res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop,
- sinkpad);
+ sinkpad, NULL);
} else {
demux->random_access = FALSE;
res = gst_pad_stop_task (sinkpad);
ret = gst_flv_demux_push_src_event (demux, event);
break;
case GST_EVENT_EOS:
+ {
+ GstIndex *index;
+
GST_DEBUG_OBJECT (demux, "received EOS");
- if (demux->index) {
+
+ index = gst_flv_demux_get_index (GST_ELEMENT (demux));
+
+ if (index) {
GST_DEBUG_OBJECT (demux, "committing index");
- gst_index_commit (demux->index, demux->index_id);
- }
- if (!demux->no_more_pads) {
- gst_element_no_more_pads (GST_ELEMENT (demux));
- demux->no_more_pads = TRUE;
+ gst_index_commit (index, demux->index_id);
+ gst_object_unref (index);
}
- if (!gst_flv_demux_push_src_event (demux, event))
- GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
+ if (!demux->audio_pad && !demux->video_pad)
+ GST_ELEMENT_ERROR (demux, STREAM, FAILED,
+ ("Internal data stream error."), ("Got EOS before any data"));
+ else {
+ if (!demux->no_more_pads) {
+ gst_element_no_more_pads (GST_ELEMENT (demux));
+ demux->no_more_pads = TRUE;
+ }
+
+ if (!gst_flv_demux_push_src_event (demux, event))
+ GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
+ }
ret = TRUE;
break;
+ }
case GST_EVENT_SEGMENT:
{
GstSegment in_segment;
}
}
res = TRUE;
+ /* FIXME, check index this way is not thread safe */
if (fmt != GST_FORMAT_TIME || !demux->index) {
gst_query_set_seeking (query, fmt, FALSE, -1, -1);
} else if (demux->random_access) {
gst_flv_demux_set_index (GstElement * element, GstIndex * index)
{
GstFlvDemux *demux = GST_FLV_DEMUX (element);
+ GstIndex *old_index;
GST_OBJECT_LOCK (demux);
- if (demux->index)
- gst_object_unref (demux->index);
+
+ old_index = demux->index;
+
if (index) {
demux->index = gst_object_ref (index);
demux->own_index = FALSE;
} else
demux->index = NULL;
+ if (old_index)
+ gst_object_unref (demux->index);
+
+ gst_object_ref (index);
+
GST_OBJECT_UNLOCK (demux);
+
/* object lock might be taken again */
if (index)
gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
+
GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT, demux->index);
+ gst_object_unref (index);
}
+#endif
static GstIndex *
gst_flv_demux_get_index (GstElement * element)
return result;
}
-#endif
static void
gst_flv_demux_dispose (GObject * object)
gst_static_pad_template_get (&audio_src_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&video_src_template));
- gst_element_class_set_details_simple (gstelement_class, "FLV Demuxer",
+ gst_element_class_set_static_metadata (gstelement_class, "FLV Demuxer",
"Codec/Demuxer",
"Demux FLV feeds into digital streams",
"Julien Moutte <julien@moutte.net>");
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
- "flv", "FLV muxing and demuxing plugin",
+ flv, "FLV muxing and demuxing plugin",
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)