#include <gst/base/gstbytereader.h>
#include <gst/pbutils/descriptions.h>
#include <gst/pbutils/pbutils.h>
+#include <gst/audio/audio.h>
+
+/* FIXME: don't rely on own GstIndex */
+#include "gstindex.c"
+#include "gstmemindex.c"
+#define GST_ASSOCIATION_FLAG_NONE GST_INDEX_ASSOCIATION_FLAG_NONE
+#define GST_ASSOCIATION_FLAG_KEY_UNIT GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT
+#define GST_ASSOCIATION_FLAG_DELTA_UNIT GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT
static GstStaticPadTemplate flv_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_STATIC_CAPS
("audio/x-adpcm, layout = (string) swf, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
"audio/mpeg, mpegversion = (int) 1, layer = (int) 3, channels = (int) { 1, 2 }, rate = (int) { 5512, 8000, 11025, 22050, 44100 }, parsed = (boolean) TRUE; "
- "audio/mpeg, mpegversion = (int) 4, framed = (boolean) TRUE; "
+ "audio/mpeg, mpegversion = (int) 4, stream-format = (string) raw, framed = (boolean) TRUE; "
"audio/x-nellymoser, channels = (int) { 1, 2 }, rate = (int) { 5512, 8000, 11025, 16000, 22050, 44100 }; "
- "audio/x-raw-int, endianness = (int) LITTLE_ENDIAN, channels = (int) { 1, 2 }, width = (int) 8, depth = (int) 8, rate = (int) { 5512, 11025, 22050, 44100 }, signed = (boolean) FALSE; "
- "audio/x-raw-int, endianness = (int) LITTLE_ENDIAN, channels = (int) { 1, 2 }, width = (int) 16, depth = (int) 16, rate = (int) { 5512, 11025, 22050, 44100 }, signed = (boolean) TRUE; "
+ "audio/x-raw, format = (string) { U8, S16LE }, layout = (string) interleaved, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
"audio/x-alaw, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
"audio/x-mulaw, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
"audio/x-speex, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 };")
/* 1 byte of tag type + 3 bytes of tag data size */
#define FLV_TAG_TYPE_SIZE 4
+/* two seconds - consider pts are resynced to another base if this different */
+#define RESYNC_THRESHOLD 2000
+
static gboolean flv_demux_handle_seek_push (GstFlvDemux * demux,
GstEvent * event);
static gboolean gst_flv_demux_handle_seek_pull (GstFlvDemux * demux,
GstEvent * event, gboolean seeking);
-static gboolean gst_flv_demux_query (GstPad * pad, GstQuery * query);
-static gboolean gst_flv_demux_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_flv_demux_query (GstPad * pad, GstObject * parent,
+ GstQuery * query);
+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) {
#ifndef GST_DISABLE_GST_DEBUG
- gint64 time;
+ gint64 time = 0;
gboolean key;
gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
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 *
return string;
}
-static const GstQueryType *
-gst_flv_demux_query_types (GstPad * pad)
-{
- static const GstQueryType query_types[] = {
- GST_QUERY_DURATION,
- GST_QUERY_POSITION,
- GST_QUERY_SEEKING,
- 0
- };
-
- return query_types;
-}
-
static void
gst_flv_demux_check_seekability (GstFlvDemux * demux)
{
/* try harder to query upstream size if we didn't get it the first time */
if (demux->upstream_seekable && stop == -1) {
GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
- gst_pad_query_peer_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
+ gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
}
/* if upstream doesn't know the size, it's likely that it's not seekable in
GstFlowReturn ret = GST_FLOW_OK;
GstByteReader reader;
guint8 type = 0;
- guint8 *data;
- gsize size;
+ GstMapInfo map;
g_return_val_if_fail (gst_buffer_get_size (buffer) >= 7, GST_FLOW_ERROR);
- data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
- gst_byte_reader_init (&reader, data, size);
+ 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 */
}
cleanup:
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return ret;
}
break;
case 0:
case 3:
+ {
+ GstAudioFormat format;
+
/* Assuming little endian for 0 (aka endianness of the
* system on which the file was created) as most people
* are probably using little endian machines */
- caps = gst_caps_new_simple ("audio/x-raw-int",
- "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
- "signed", G_TYPE_BOOLEAN, (width == 8) ? FALSE : TRUE,
- "width", G_TYPE_INT, width, "depth", G_TYPE_INT, width, NULL);
+ format = gst_audio_format_build_integer ((width == 8) ? FALSE : TRUE,
+ G_LITTLE_ENDIAN, width, width);
+
+ caps = gst_caps_new_simple ("audio/x-raw",
+ "format", G_TYPE_STRING, gst_audio_format_to_string (format),
+ "layout", G_TYPE_STRING, "interleaved", NULL);
break;
+ }
case 4:
case 5:
case 6:
- caps = gst_caps_new_simple ("audio/x-nellymoser", NULL);
+ caps = gst_caps_new_empty_simple ("audio/x-nellymoser");
break;
case 10:
{
- guint8 *data = NULL;
- gsize size;
-
- if (demux->audio_codec_data)
- data = gst_buffer_map (demux->audio_codec_data, &size, NULL,
- GST_MAP_READ);
- /* use codec-data to extract and verify samplerate */
- if (demux->audio_codec_data && size >= 2) {
- gint freq_index;
-
- freq_index = GST_READ_UINT16_BE (data);
- freq_index = (freq_index & 0x0780) >> 7;
- adjusted_rate =
- gst_codec_utils_aac_get_sample_rate_from_index (freq_index);
-
- if (adjusted_rate && (rate != adjusted_rate)) {
- GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate,
- adjusted_rate);
- } else {
- adjusted_rate = rate;
+ if (demux->audio_codec_data) {
+ GstMapInfo map;
+
+ gst_buffer_map (demux->audio_codec_data, &map, GST_MAP_READ);
+
+ /* use codec-data to extract and verify samplerate */
+ if (map.size >= 2) {
+ gint freq_index;
+
+ freq_index = GST_READ_UINT16_BE (map.data);
+ freq_index = (freq_index & 0x0780) >> 7;
+ adjusted_rate =
+ gst_codec_utils_aac_get_sample_rate_from_index (freq_index);
+
+ if (adjusted_rate && (rate != adjusted_rate)) {
+ GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate,
+ adjusted_rate);
+ } else {
+ adjusted_rate = rate;
+ }
}
+ gst_buffer_unmap (demux->audio_codec_data, &map);
}
- if (data)
- gst_buffer_unmap (demux->audio_codec_data, data, -1);
+
caps = gst_caps_new_simple ("audio/mpeg",
"mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
"stream-format", G_TYPE_STRING, "raw", NULL);
break;
}
case 7:
- caps = gst_caps_new_simple ("audio/x-alaw", NULL);
+ caps = gst_caps_new_empty_simple ("audio/x-alaw");
break;
case 8:
- caps = gst_caps_new_simple ("audio/x-mulaw", NULL);
+ caps = gst_caps_new_empty_simple ("audio/x-mulaw");
break;
case 11:
- caps = gst_caps_new_simple ("audio/x-speex", NULL);
+ caps = gst_caps_new_empty_simple ("audio/x-speex");
break;
default:
GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
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 (codec_name) {
if (demux->taglist == NULL)
- demux->taglist = gst_tag_list_new ();
+ demux->taglist = gst_tag_list_new_empty ();
gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
GST_TAG_AUDIO_CODEC, codec_name, NULL);
g_free (codec_name);
return ret;
}
+static gboolean
+gst_flv_demux_push_src_event (GstFlvDemux * demux, GstEvent * event)
+{
+ gboolean ret = TRUE;
+
+ if (demux->audio_pad)
+ ret |= gst_pad_push_event (demux->audio_pad, gst_event_ref (event));
+
+ if (demux->video_pad)
+ ret |= gst_pad_push_event (demux->video_pad, gst_event_ref (event));
+
+ gst_event_unref (event);
+
+ return ret;
+}
+
static void
gst_flv_demux_push_tags (GstFlvDemux * demux)
{
if (demux->taglist) {
GST_DEBUG_OBJECT (demux, "pushing tags out %" GST_PTR_FORMAT,
demux->taglist);
- gst_element_found_tags (GST_ELEMENT (demux), demux->taglist);
- demux->taglist = gst_tag_list_new ();
+ 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;
}
}
+static void
+gst_flv_demux_update_resync (GstFlvDemux * demux, guint32 pts, gboolean discont,
+ guint32 * last, GstClockTime * offset)
+{
+ gint32 dpts = pts - *last;
+ if (!discont && ABS (dpts) >= RESYNC_THRESHOLD) {
+ /* Theoretically, we should use substract the duration of the last buffer,
+ but this demuxer sends no durations on buffers, not sure if it cannot
+ know, or just does not care to calculate. */
+ *offset -= dpts * GST_MSECOND;
+ GST_WARNING_OBJECT (demux,
+ "Large pts gap (%" G_GINT32_FORMAT " ms), assuming resync, offset now %"
+ GST_TIME_FORMAT "", dpts, GST_TIME_ARGS (*offset));
+ }
+ *last = pts;
+}
+
static GstFlowReturn
gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
{
guint32 pts = 0, codec_tag = 0, rate = 5512, width = 8, channels = 1;
guint32 codec_data = 0, pts_ext = 0;
guint8 flags = 0;
- guint8 *data;
+ GstMapInfo map;
GstBuffer *outbuf;
- gsize size;
+ guint8 *data;
GST_LOG_OBJECT (demux, "parsing an audio tag");
/* Error out on tags with too small headers */
if (gst_buffer_get_size (buffer) < 11) {
- GST_ERROR_OBJECT (demux, "Too small tag size (%d)",
+ GST_ERROR_OBJECT (demux, "Too small tag size (%" G_GSIZE_FORMAT ")",
gst_buffer_get_size (buffer));
return GST_FLOW_ERROR;
}
- data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ data = map.data;
/* Grab information about audio tag */
pts = GST_READ_UINT24_BE (data);
flags = GST_READ_UINT8 (data + 7);
/* Silently skip buffers with no data */
- if (size == 11)
+ if (map.size == 11)
goto beach;
/* Channels */
goto beach;
}
+ /* Set functions on the pad */
+ gst_pad_set_query_function (demux->audio_pad,
+ GST_DEBUG_FUNCPTR (gst_flv_demux_query));
+ gst_pad_set_event_function (demux->audio_pad,
+ GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
+
+ gst_pad_use_fixed_caps (demux->audio_pad);
+
+ /* Make it active */
+ gst_pad_set_active (demux->audio_pad, TRUE);
+
/* Negotiate caps */
if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
width)) {
}
#endif
- /* Set functions on the pad */
- gst_pad_set_query_type_function (demux->audio_pad,
- GST_DEBUG_FUNCPTR (gst_flv_demux_query_types));
- gst_pad_set_query_function (demux->audio_pad,
- GST_DEBUG_FUNCPTR (gst_flv_demux_query));
- gst_pad_set_event_function (demux->audio_pad,
- GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
-
- gst_pad_use_fixed_caps (demux->audio_pad);
-
- /* Make it active */
- gst_pad_set_active (demux->audio_pad, TRUE);
-
/* We need to set caps before adding */
gst_element_add_pad (GST_ELEMENT (demux),
gst_object_ref (demux->audio_pad));
}
}
+ /* detect (and deem to be resyncs) large pts gaps */
+ gst_flv_demux_update_resync (demux, pts, demux->audio_need_discont,
+ &demux->last_audio_pts, &demux->audio_time_offset);
+
/* Fill buffer with data */
- GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND;
+ GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND + demux->audio_time_offset;
GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
/* 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);
}
/* Do we need a newsegment event ? */
if (G_UNLIKELY (demux->audio_need_segment)) {
- /* FIXME need one segment sent for all stream to maintain a/v sync */
if (!demux->new_seg_event) {
GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
demux->audio_need_segment = FALSE;
}
- GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
+ GST_LOG_OBJECT (demux,
+ "pushing %" G_GSIZE_FORMAT " bytes buffer at pts %" GST_TIME_FORMAT
" with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
gst_buffer_get_size (outbuf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
/* Push downstream */
ret = gst_pad_push (demux->audio_pad, outbuf);
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
- if (demux->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
+ if (demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
demux->segment.position > demux->segment.stop) {
- /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
+ /* In reverse playback we can get a GST_FLOW_EOS when
* we are at the end of the segment, so we just need to jump
* back to the previous section. */
GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
demux->audio_linked = TRUE;
beach:
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return ret;
}
/* Generate caps for that pad */
switch (codec_tag) {
case 2:
- caps = gst_caps_new_simple ("video/x-flash-video", NULL);
+ caps = gst_caps_new_empty_simple ("video/x-flash-video");
break;
case 3:
- caps = gst_caps_new_simple ("video/x-flash-screen", NULL);
+ caps = gst_caps_new_empty_simple ("video/x-flash-screen");
break;
case 4:
- caps = gst_caps_new_simple ("video/x-vp6-flash", NULL);
+ caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
break;
case 5:
- caps = gst_caps_new_simple ("video/x-vp6-alpha", NULL);
+ caps = gst_caps_new_empty_simple ("video/x-vp6-alpha");
break;
case 7:
caps =
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 (codec_name) {
if (demux->taglist == NULL)
- demux->taglist = gst_tag_list_new ();
+ demux->taglist = gst_tag_list_new_empty ();
gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
GST_TAG_VIDEO_CODEC, codec_name, NULL);
g_free (codec_name);
guint32 pts = 0, codec_data = 1, pts_ext = 0;
gboolean keyframe = FALSE;
guint8 flags = 0, codec_tag = 0;
- guint8 *data;
GstBuffer *outbuf;
- gsize size;
+ GstMapInfo map;
+ guint8 *data;
g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
GST_FLOW_ERROR);
return GST_FLOW_ERROR;
}
- data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ data = map.data;
/* Grab information about video tag */
pts = GST_READ_UINT24_BE (data);
GST_LOG_OBJECT (demux, "got cts %d", cts);
- pts = pts + cts;
+ /* avoid negative overflow */
+ if (cts >= 0 || pts >= -cts)
+ pts += cts;
}
GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
goto beach;
}
+ /* Set functions on the pad */
+ gst_pad_set_query_function (demux->video_pad,
+ GST_DEBUG_FUNCPTR (gst_flv_demux_query));
+ gst_pad_set_event_function (demux->video_pad,
+ GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
+
+ gst_pad_use_fixed_caps (demux->video_pad);
+
+ /* Make it active */
+ gst_pad_set_active (demux->video_pad, TRUE);
+
+ /* Needs to be active before setting caps */
if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
gst_object_unref (demux->video_pad);
demux->video_pad = NULL;
}
#endif
- /* Set functions on the pad */
- gst_pad_set_query_type_function (demux->video_pad,
- GST_DEBUG_FUNCPTR (gst_flv_demux_query_types));
- gst_pad_set_query_function (demux->video_pad,
- GST_DEBUG_FUNCPTR (gst_flv_demux_query));
- gst_pad_set_event_function (demux->video_pad,
- GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
-
- gst_pad_use_fixed_caps (demux->video_pad);
-
- /* Make it active */
- gst_pad_set_active (demux->video_pad, TRUE);
-
/* We need to set caps before adding */
gst_element_add_pad (GST_ELEMENT (demux),
gst_object_ref (demux->video_pad));
}
}
+ /* detect (and deem to be resyncs) large pts gaps */
+ gst_flv_demux_update_resync (demux, pts, demux->video_need_discont,
+ &demux->last_video_pts, &demux->video_time_offset);
+
/* Fill buffer with data */
- GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND;
+ GST_BUFFER_TIMESTAMP (outbuf) = pts * GST_MSECOND + demux->video_time_offset;
GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
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);
}
/* Do we need a newsegment event ? */
if (G_UNLIKELY (demux->video_need_segment)) {
- /* FIXME need one segment sent for all stream to maintain a/v sync */
if (!demux->new_seg_event) {
GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
demux->video_need_segment = FALSE;
}
- GST_LOG_OBJECT (demux, "pushing %d bytes buffer at pts %" GST_TIME_FORMAT
+ GST_LOG_OBJECT (demux,
+ "pushing %" G_GSIZE_FORMAT " bytes buffer at pts %" GST_TIME_FORMAT
" with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
", keyframe (%d)", gst_buffer_get_size (outbuf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
ret = gst_pad_push (demux->video_pad, outbuf);
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
- if (demux->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
+ if (demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
demux->segment.position > demux->segment.stop) {
- /* In reverse playback we can get a GST_FLOW_UNEXPECTED when
+ /* In reverse playback we can get a GST_FLOW_EOS when
* we are at the end of the segment, so we just need to jump
* back to the previous section. */
GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
demux->video_linked = TRUE;
beach:
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return ret;
}
guint8 type;
gboolean keyframe = TRUE;
GstClockTime ret = GST_CLOCK_TIME_NONE;
- guint8 *data, *bdata;
+ GstMapInfo map;
+ guint8 *data;
gsize size;
g_return_val_if_fail (gst_buffer_get_size (buffer) >= 12,
GST_CLOCK_TIME_NONE);
- data = bdata = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ data = map.data;
+ size = map.size;
type = data[0];
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->duration = ret;
exit:
- gst_buffer_unmap (buffer, bdata, -1);
+ gst_buffer_unmap (buffer, &map);
return ret;
}
{
GstFlowReturn ret = GST_FLOW_OK;
guint8 tag_type = 0;
- guint8 *data;
+ GstMapInfo map;
g_return_val_if_fail (gst_buffer_get_size (buffer) >= 4, GST_FLOW_ERROR);
- data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
- tag_type = data[0];
+ tag_type = map.data[0];
switch (tag_type) {
case 9:
/* Tag size is 1 byte of type + 3 bytes of size + 7 bytes + tag data size +
* 4 bytes of previous tag size */
- demux->tag_data_size = GST_READ_UINT24_BE (data + 1);
+ demux->tag_data_size = GST_READ_UINT24_BE (map.data + 1);
demux->tag_size = demux->tag_data_size + 11;
GST_LOG_OBJECT (demux, "tag data size is %" G_GUINT64_FORMAT,
demux->tag_data_size);
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return ret;
}
gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
{
GstFlowReturn ret = GST_FLOW_OK;
- guint8 *data;
+ GstMapInfo map;
g_return_val_if_fail (gst_buffer_get_size (buffer) >= 9, GST_FLOW_ERROR);
- data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
/* Check for the FLV tag */
- if (data[0] == 'F' && data[1] == 'L' && data[2] == 'V') {
+ if (map.data[0] == 'F' && map.data[1] == 'L' && map.data[2] == 'V') {
GST_DEBUG_OBJECT (demux, "FLV header detected");
} else {
if (G_UNLIKELY (demux->strict)) {
GST_WARNING_OBJECT (demux, "invalid header tag detected");
- ret = GST_FLOW_UNEXPECTED;
+ ret = GST_FLOW_EOS;
goto beach;
}
}
/* Now look at audio/video flags */
{
- guint8 flags = data[4];
+ guint8 flags = map.data[4];
demux->has_video = demux->has_audio = FALSE;
demux->need_header = FALSE;
beach:
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
return ret;
}
demux->index_max_time = 0;
demux->audio_start = demux->video_start = GST_CLOCK_TIME_NONE;
+ demux->last_audio_pts = demux->last_video_pts = 0;
+ demux->audio_time_offset = demux->video_time_offset = 0;
demux->no_more_pads = FALSE;
}
static GstFlowReturn
-gst_flv_demux_chain (GstPad * pad, GstBuffer * buffer)
+gst_flv_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
GstFlowReturn ret = GST_FLOW_OK;
GstFlvDemux *demux = NULL;
- demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
+ demux = GST_FLV_DEMUX (parent);
- GST_LOG_OBJECT (demux, "received buffer of %d bytes at offset %"
+ GST_LOG_OBJECT (demux,
+ "received buffer of %" G_GSIZE_FORMAT " bytes at offset %"
G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
GST_BUFFER_OFFSET (buffer));
if (G_UNLIKELY (demux->flushing)) {
GST_DEBUG_OBJECT (demux, "we are now flushing, exiting parser loop");
- ret = GST_FLOW_WRONG_STATE;
+ ret = GST_FLOW_FLUSHING;
goto beach;
}
}
}
- gst_object_unref (demux);
-
return ret;
/* ERRORS */
if (G_UNLIKELY (*buffer && gst_buffer_get_size (*buffer) != size)) {
GST_WARNING_OBJECT (demux,
- "partial pull got %d when expecting %d from offset %" G_GUINT64_FORMAT,
- gst_buffer_get_size (*buffer), size, offset);
+ "partial pull got %" G_GSIZE_FORMAT " when expecting %d from offset %"
+ G_GUINT64_FORMAT, gst_buffer_get_size (*buffer), size, offset);
gst_buffer_unref (*buffer);
- ret = GST_FLOW_UNEXPECTED;
+ ret = GST_FLOW_EOS;
*buffer = NULL;
return ret;
}
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;
static GstFlowReturn
gst_flv_demux_seek_to_prev_keyframe (GstFlvDemux * demux)
{
- GstFlowReturn ret = GST_FLOW_UNEXPECTED;
+ 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, 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);
-
- /* setup for next section */
- demux->to_offset = demux->from_offset;
- gst_flv_demux_move_to_offset (demux, bytes, FALSE);
- ret = GST_FLOW_OK;
- }
+ if (entry) {
+ gint64 bytes = 0, time = 0;
-done:
- return ret;
-}
+ gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
+ gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
-static gboolean
-gst_flv_demux_push_src_event (GstFlvDemux * demux, GstEvent * event)
-{
- gboolean ret = TRUE;
+ 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);
- if (demux->audio_pad)
- ret |= gst_pad_push_event (demux->audio_pad, gst_event_ref (event));
+ /* setup for next section */
+ demux->to_offset = demux->from_offset;
+ gst_flv_demux_move_to_offset (demux, bytes, FALSE);
+ ret = GST_FLOW_OK;
+ }
- if (demux->video_pad)
- ret |= gst_pad_push_event (demux->video_pad, gst_event_ref (event));
+ gst_object_unref (index);
+ }
- gst_event_unref (event);
+done:
return ret;
}
GstClockTime tag_time;
GstFlowReturn ret = GST_FLOW_OK;
- if (!gst_pad_query_peer_duration (demux->sinkpad, GST_FORMAT_BYTES, &size))
+ if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &size))
return GST_FLOW_OK;
GST_DEBUG_OBJECT (demux, "building index at %" G_GINT64_FORMAT
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;
demux->offset += tag_size;
}
- if (ret == GST_FLOW_UNEXPECTED) {
+ if (ret == GST_FLOW_EOS) {
/* file ran out, so mark we have complete index */
demux->indexed = TRUE;
ret = GST_FLOW_OK;
gint64 ret = 0, offset;
size_t tag_size, size;
GstBuffer *buffer = NULL;
- guint8 *data;
+ GstMapInfo map;
- if (!gst_pad_query_peer_duration (demux->sinkpad, GST_FORMAT_BYTES, &offset))
+ if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &offset))
goto exit;
ret = offset;
4, &buffer))
goto exit;
- data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
- tag_size = GST_READ_UINT32_BE (data);
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ tag_size = GST_READ_UINT32_BE (map.data);
+ gst_buffer_unmap (buffer, &map);
GST_DEBUG_OBJECT (demux, "last tag size: %" G_GSIZE_FORMAT, tag_size);
gst_buffer_unref (buffer);
buffer = NULL;
goto exit;
/* a consistency check */
- data = gst_buffer_map (buffer, NULL, NULL, GST_MAP_READ);
- size = GST_READ_UINT24_BE (data + 1);
+ gst_buffer_map (buffer, &map, GST_MAP_READ);
+ size = GST_READ_UINT24_BE (map.data + 1);
if (size != tag_size - 11) {
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
GST_DEBUG_OBJECT (demux,
"tag size %" G_GSIZE_FORMAT ", expected %" G_GSIZE_FORMAT
", corrupt or truncated file", size, tag_size - 11);
gst_flv_demux_parse_tag_timestamp (demux, FALSE, buffer, &size);
/* maybe get some more metadata */
- if (data[0] == 18) {
- gst_buffer_unmap (buffer, data, -1);
+ if (map.data[0] == 18) {
+ gst_buffer_unmap (buffer, &map);
gst_buffer_unref (buffer);
buffer = NULL;
GST_DEBUG_OBJECT (demux, "script tag, pulling it to parse");
tag_size, &buffer))
gst_flv_demux_parse_tag_script (demux, buffer);
} else {
- gst_buffer_unmap (buffer, data, -1);
+ gst_buffer_unmap (buffer, &map);
}
exit:
demux->file_size = gst_flv_demux_get_metadata (demux);
break;
case FLV_STATE_DONE:
- ret = GST_FLOW_UNEXPECTED;
+ ret = GST_FLOW_EOS;
break;
case FLV_STATE_SEEK:
/* seek issued with insufficient index;
/* check EOS condition */
if ((demux->segment.stop != -1) &&
(demux->segment.position >= demux->segment.stop)) {
- ret = GST_FLOW_UNEXPECTED;
+ ret = GST_FLOW_EOS;
}
}
GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
gst_pad_pause_task (pad);
- if (ret == GST_FLOW_UNEXPECTED) {
+ if (ret == GST_FLOW_EOS) {
/* handle end-of-stream/segment */
/* so align our position with the end of it, if there is one
* this ensures a subsequent will arrive at correct base/acc time */
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_UNEXPECTED) {
+ } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
GST_ELEMENT_ERROR (demux, STREAM, FAILED,
("Internal data stream error."),
("stream stopped, reason %s", reason));
{
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;
if (!building_index) {
demux->building_index = TRUE;
if (!demux->file_size
- && !gst_pad_query_peer_duration (demux->sinkpad, GST_FORMAT_BYTES,
+ && !gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES,
&demux->file_size)) {
GST_WARNING_OBJECT (demux, "Failed to query upstream file size");
GST_OBJECT_UNLOCK (demux);
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 we can pull that's prefered */
static gboolean
-gst_flv_demux_sink_activate (GstPad * sinkpad)
+gst_flv_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
{
GstQuery *query;
gboolean pull_mode;
goto activate_push;
}
- gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL);
+ pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
gst_query_unref (query);
if (!pull_mode)
goto activate_push;
GST_DEBUG_OBJECT (sinkpad, "activating pull");
- return gst_pad_activate_pull (sinkpad, TRUE);
+ return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
activate_push:
{
GST_DEBUG_OBJECT (sinkpad, "activating push");
- return gst_pad_activate_push (sinkpad, TRUE);
+ return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
}
}
-/* This function gets called when we activate ourselves in push mode.
- * We cannot seek (ourselves) in the stream */
static gboolean
-gst_flv_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
+gst_flv_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
+ GstPadMode mode, gboolean active)
{
+ gboolean res;
GstFlvDemux *demux;
- demux = GST_FLV_DEMUX (gst_pad_get_parent (sinkpad));
-
- demux->random_access = FALSE;
-
- gst_object_unref (demux);
-
- return TRUE;
-}
+ demux = GST_FLV_DEMUX (parent);
-/* this function gets called when we activate ourselves in pull mode.
- * We can perform random access to the resource and we start a task
- * to start reading */
-static gboolean
-gst_flv_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
-{
- GstFlvDemux *demux;
-
- demux = GST_FLV_DEMUX (gst_pad_get_parent (sinkpad));
-
- if (active) {
- demux->random_access = TRUE;
- gst_object_unref (demux);
- return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop,
- sinkpad);
- } else {
- demux->random_access = FALSE;
- gst_object_unref (demux);
- return gst_pad_stop_task (sinkpad);
+ switch (mode) {
+ case GST_PAD_MODE_PUSH:
+ demux->random_access = FALSE;
+ res = TRUE;
+ break;
+ case GST_PAD_MODE_PULL:
+ if (active) {
+ demux->random_access = TRUE;
+ res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop,
+ sinkpad, NULL);
+ } else {
+ demux->random_access = FALSE;
+ res = gst_pad_stop_task (sinkpad);
+ }
+ break;
+ default:
+ res = FALSE;
+ break;
}
+ return res;
}
static gboolean
-gst_flv_demux_sink_event (GstPad * pad, GstEvent * event)
+gst_flv_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstFlvDemux *demux;
gboolean ret = FALSE;
- demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
+ demux = GST_FLV_DEMUX (parent);
GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
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;
break;
}
- gst_object_unref (demux);
-
return ret;
}
static gboolean
-gst_flv_demux_src_event (GstPad * pad, GstEvent * event)
+gst_flv_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
GstFlvDemux *demux;
gboolean ret = FALSE;
- demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
+ demux = GST_FLV_DEMUX (parent);
GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
break;
}
- gst_object_unref (demux);
-
return ret;
}
static gboolean
-gst_flv_demux_query (GstPad * pad, GstQuery * query)
+gst_flv_demux_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
gboolean res = TRUE;
GstFlvDemux *demux;
- demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
+ demux = GST_FLV_DEMUX (parent);
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_DURATION:
}
}
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) {
}
case GST_QUERY_LATENCY:
default:
- {
- GstPad *peer;
-
- if ((peer = gst_pad_get_peer (demux->sinkpad))) {
- /* query latency on peer pad */
- res = gst_pad_query (peer, query);
- gst_object_unref (peer);
- } else {
- /* no peer, we don't know */
- res = FALSE;
- }
+ res = gst_pad_query_default (pad, parent, query);
break;
- }
}
beach:
- gst_object_unref (demux);
return res;
}
if (G_UNLIKELY (!demux->index)) {
GST_DEBUG_OBJECT (demux, "no index provided creating our own");
- demux->index = gst_index_factory_make ("memindex");
+ demux->index = g_object_new (gst_mem_index_get_type (), NULL);
gst_index_get_writer_id (demux->index, GST_OBJECT (demux),
&demux->index_id);
return ret;
}
+#if 0
static void
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)
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_flv_demux_change_state);
+
+#if 0
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_flv_demux_set_index);
gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_flv_demux_get_index);
+#endif
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&flv_sink_template));
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_DEBUG_FUNCPTR (gst_flv_demux_chain));
gst_pad_set_activate_function (demux->sinkpad,
GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate));
- gst_pad_set_activatepull_function (demux->sinkpad,
- GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate_pull));
- gst_pad_set_activatepush_function (demux->sinkpad,
- GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate_push));
+ gst_pad_set_activatemode_function (demux->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate_mode));
gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
demux->adapter = gst_adapter_new ();
- demux->taglist = gst_tag_list_new ();
+ demux->taglist = gst_tag_list_new_empty ();
gst_segment_init (&demux->segment, GST_FORMAT_TIME);
demux->own_index = FALSE;
+ GST_OBJECT_FLAG_SET (demux, GST_ELEMENT_FLAG_INDEXABLE);
+
gst_flv_demux_cleanup (demux);
}
}
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)