#include <gst/gst.h>
#include <tremor/ivorbiscodec.h>
#include <tremor/ivorbisfile.h>
-#include <gst/bytestream/bytestream.h>
+#include <gst/base/gstadapter.h>
GST_DEBUG_CATEGORY_STATIC (ivorbisfile_debug);
#define GST_CAT_DEFAULT ivorbisfile_debug
-#define GST_TYPE_IVORBISFILE \
+#define GST_TYPE_IVORBISFILE \
(ivorbisfile_get_type())
-#define GST_IVORBISFILE(obj) \
+#define GST_IVORBISFILE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IVORBISFILE,Ivorbisfile))
-#define GST_IVORBISFILE_CLASS(klass) \
+#define GST_IVORBISFILE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IVORBISFILE,IvorbisfileClass))
-#define GST_IS_IVORBISFILE(obj) \
+#define GST_IS_IVORBISFILE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IVORBISFILE))
-#define GST_IS_IVORBISFILE_CLASS(obj) \
+#define GST_IS_IVORBISFILE_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IVORBISFILE))
typedef struct _Ivorbisfile Ivorbisfile;
GstElement element;
GstPad *sinkpad, *srcpad;
- GstByteStream *bs;
+ GstAdapter *adapter;
+ guint64 adapterOffset;
OggVorbis_File vf;
gint current_link;
guint64 total_bytes;
guint64 offset;
+ gint rate;
+ gint channels;
+ gint width;
+
GstCaps *metadata;
GstCaps *streaminfo;
};
static GstStateChangeReturn
gst_ivorbisfile_change_state (GstElement * element, GstStateChange transition);
-static const GstFormat *gst_ivorbisfile_get_formats (GstPad * pad);
static gboolean gst_ivorbisfile_src_convert (GstPad * pad,
GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
static gboolean gst_ivorbisfile_sink_convert (GstPad * pad,
GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
-static const GstQueryType *gst_ivorbisfile_get_query_types (GstPad * pad);
+static const GstQueryType *gst_ivorbisfile_get_src_query_types (GstPad * pad);
+
+static gboolean gst_ivorbisfile_src_query (GstPad * pad, GstQuery * query);
-static gboolean gst_ivorbisfile_src_query (GstPad * pad,
- GstQueryType type, GstFormat * format, gint64 * value);
-static const GstEventMask *gst_ivorbisfile_get_event_masks (GstPad * pad);
static gboolean gst_ivorbisfile_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_ivorbisfile_sink_event (GstPad * pad, GstEvent * event);
+
+static const GstQueryType *gst_ivorbisfile_get_sink_query_types (GstPad * pad);
+
+static gboolean gst_ivorbisfile_sink_query (GstPad * pad, GstQuery * query);
+
static void gst_ivorbisfile_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
static void gst_ivorbisfile_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_ivorbisfile_loop (GstElement * element);
+static gboolean gst_ivorbisfile_sink_activate (GstPad * sinkpad);
-static GstElementClass *parent_class = NULL;
+static gboolean
+gst_ivorbisfile_sink_activate_pull (GstPad * sinkpad, gboolean active);
+
+static void gst_ivorbisfile_loop (GstPad * pad);
-//static guint gst_ivorbisfile_signals[LAST_SIGNAL] = { 0 };
+static GstElementClass *parent_class = NULL;
static GstFormat logical_stream_format;
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+ gobject_class->get_property = gst_ivorbisfile_get_property;
+ gobject_class->set_property = gst_ivorbisfile_set_property;
+
g_object_class_install_property (gobject_class, ARG_METADATA,
g_param_spec_boxed ("metadata", "Metadata", "(logical) Stream metadata",
GST_TYPE_CAPS, G_PARAM_READABLE));
g_param_spec_boxed ("streaminfo", "stream",
"(logical) Stream information", GST_TYPE_CAPS, G_PARAM_READABLE));
- gobject_class->get_property = gst_ivorbisfile_get_property;
- gobject_class->set_property = gst_ivorbisfile_set_property;
gstelement_class->change_state = gst_ivorbisfile_change_state;
}
ivorbisfile->sinkpad = gst_pad_new_from_template (gst_vorbisdec_sink_template,
"sink");
gst_element_add_pad (GST_ELEMENT (ivorbisfile), ivorbisfile->sinkpad);
- gst_pad_set_formats_function (ivorbisfile->sinkpad,
- gst_ivorbisfile_get_formats);
- gst_pad_set_convert_function (ivorbisfile->sinkpad,
- gst_ivorbisfile_sink_convert);
- gst_element_set_loop_function (GST_ELEMENT (ivorbisfile),
- gst_ivorbisfile_loop);
+ gst_pad_set_query_type_function (ivorbisfile->sinkpad,
+ gst_ivorbisfile_get_sink_query_types);
+ gst_pad_set_query_function (ivorbisfile->sinkpad, gst_ivorbisfile_sink_query);
+
+ gst_pad_set_activate_function (ivorbisfile->sinkpad,
+ gst_ivorbisfile_sink_activate);
+ gst_pad_set_activatepull_function (ivorbisfile->sinkpad,
+ gst_ivorbisfile_sink_activate_pull);
+
+ gst_pad_set_event_function (ivorbisfile->sinkpad, gst_ivorbisfile_sink_event);
+
ivorbisfile->srcpad =
gst_pad_new_from_template (gst_vorbisdec_src_template, "src");
gst_element_add_pad (GST_ELEMENT (ivorbisfile), ivorbisfile->srcpad);
- gst_pad_set_formats_function (ivorbisfile->srcpad,
- gst_ivorbisfile_get_formats);
+
gst_pad_set_query_type_function (ivorbisfile->srcpad,
- gst_ivorbisfile_get_query_types);
+ gst_ivorbisfile_get_src_query_types);
gst_pad_set_query_function (ivorbisfile->srcpad, gst_ivorbisfile_src_query);
- gst_pad_set_event_mask_function (ivorbisfile->srcpad,
- gst_ivorbisfile_get_event_masks);
+
gst_pad_set_event_function (ivorbisfile->srcpad, gst_ivorbisfile_src_event);
- gst_pad_set_convert_function (ivorbisfile->srcpad,
- gst_ivorbisfile_src_convert);
ivorbisfile->total_bytes = 0;
ivorbisfile->offset = 0;
ivorbisfile->metadata = NULL;
ivorbisfile->streaminfo = NULL;
ivorbisfile->current_link = -1;
+
+ ivorbisfile->rate = -1;
+ ivorbisfile->channels = -1;
+ ivorbisfile->width = -1;
+
}
/* the next four functions are the ov callbacks we provide to ivorbisfile
static size_t
gst_ivorbisfile_read (void *ptr, size_t size, size_t nmemb, void *datasource)
{
- guint32 got_bytes = 0;
- guint8 *data;
size_t read_size = size * nmemb;
-
+ GstBuffer *buf = NULL;
Ivorbisfile *ivorbisfile = GST_IVORBISFILE (datasource);
+ size_t ret;
GST_DEBUG ("read %d", read_size);
/* make sure we don't go to EOS */
+
if (!ivorbisfile->may_eos && ivorbisfile->total_bytes &&
ivorbisfile->offset + read_size > ivorbisfile->total_bytes) {
read_size = ivorbisfile->total_bytes - ivorbisfile->offset;
if (read_size == 0 || ivorbisfile->eos)
return 0;
- while (got_bytes == 0) {
- got_bytes = gst_bytestream_peek_bytes (ivorbisfile->bs, &data, read_size);
- if (got_bytes < read_size) {
- GstEvent *event;
- guint32 avail;
-
- gst_bytestream_get_status (ivorbisfile->bs, &avail, &event);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_EOS:
- GST_DEBUG ("eos");
- ivorbisfile->eos = TRUE;
- if (avail == 0) {
- gst_event_unref (event);
- return 0;
- }
- break;
- case GST_EVENT_DISCONTINUOUS:
- GST_DEBUG ("discont");
- ivorbisfile->need_discont = TRUE;
- default:
- break;
- }
- gst_event_unref (event);
- if (avail > 0)
- got_bytes = gst_bytestream_peek_bytes (ivorbisfile->bs, &data, avail);
- else
- got_bytes = 0;
- }
+ if (GST_FLOW_OK != gst_pad_pull_range (ivorbisfile->sinkpad,
+ ivorbisfile->offset, read_size, &buf)) {
+ return 0;
}
- memcpy (ptr, data, got_bytes);
- gst_bytestream_flush_fast (ivorbisfile->bs, got_bytes);
+ memcpy (ptr, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
- ivorbisfile->offset += got_bytes;
+ ivorbisfile->offset += GST_BUFFER_SIZE (buf);
- return got_bytes / size;
+ ret = GST_BUFFER_SIZE (buf) / size;
+ gst_buffer_unref (buf);
+
+ return ret;
}
static int
gst_ivorbisfile_seek (void *datasource, int64_t offset, int whence)
{
Ivorbisfile *ivorbisfile = GST_IVORBISFILE (datasource);
- GstSeekType method;
guint64 pending_offset = ivorbisfile->offset;
gboolean need_total = FALSE;
GST_DEBUG ("seek %" G_GINT64_FORMAT " %d", offset, whence);
if (whence == SEEK_SET) {
- method = GST_SEEK_METHOD_SET;
pending_offset = offset;
+ ivorbisfile->adapterOffset = offset;
} else if (whence == SEEK_CUR) {
- method = GST_SEEK_METHOD_CUR;
pending_offset += offset;
+ ivorbisfile->adapterOffset += offset;
} else if (whence == SEEK_END) {
- method = GST_SEEK_METHOD_END;
need_total = TRUE;
pending_offset = ivorbisfile->total_bytes - offset;
+ ivorbisfile->adapterOffset = ivorbisfile->total_bytes - offset;
} else
return -1;
- if (!gst_bytestream_seek (ivorbisfile->bs, offset, method))
- return -1;
ivorbisfile->offset = pending_offset;
if (need_total)
- ivorbisfile->total_bytes = gst_bytestream_tell (ivorbisfile->bs) + offset;
+ ivorbisfile->total_bytes = ivorbisfile->adapterOffset + offset;
return 0;
}
Ivorbisfile *ivorbisfile = GST_IVORBISFILE (datasource);
long result;
- result = gst_bytestream_tell (ivorbisfile->bs);
+ result = ivorbisfile->adapterOffset;
GST_DEBUG ("tell %ld", result);
"depth", G_TYPE_INT, 16,
"rate", G_TYPE_INT, vi->rate, "channels", G_TYPE_INT, vi->channels, NULL);
- if (gst_pad_try_set_caps (ivorbisfile->srcpad, caps) <= 0) {
+ ivorbisfile->rate = vi->rate;
+ ivorbisfile->channels = vi->channels;
+ ivorbisfile->width = 16;
+
+ if (gst_pad_set_caps (ivorbisfile->srcpad, caps) <= 0) {
res = FALSE;
}
- gst_caps_free (caps);
+ gst_caps_unref (caps);
return TRUE;
}
+
+static gboolean
+gst_ivorbisfile_sink_activate (GstPad * sinkpad)
+{
+
+ Ivorbisfile *ivorbisfile;
+
+ ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (sinkpad));
+
+ if (gst_pad_check_pull_range (sinkpad)) {
+ /* FIX ME */
+ /* ivorbisfile->vf.seekable = TRUE; */
+ ivorbisfile->vf.seekable = FALSE;
+ return gst_pad_activate_pull (sinkpad, TRUE);
+ }
+
+ ivorbisfile->vf.seekable = FALSE;
+ return FALSE;
+
+
+}
+
+
+static gboolean
+gst_ivorbisfile_sink_activate_pull (GstPad * sinkpad, gboolean active)
+{
+
+ gboolean result;
+
+ if (active) {
+ /* if we have a scheduler we can start the task */
+ result = gst_pad_start_task (sinkpad,
+ (GstTaskFunction) gst_ivorbisfile_loop, sinkpad);
+ } else {
+ result = gst_pad_stop_task (sinkpad);
+ }
+
+ return result;
+}
+
+
+
static void
-gst_ivorbisfile_loop (GstElement * element)
+gst_ivorbisfile_loop (GstPad * pad)
{
- Ivorbisfile *ivorbisfile = GST_IVORBISFILE (element);
+ Ivorbisfile *ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad));
GstBuffer *outbuf;
long ret;
GstClockTime time;
gint64 samples;
gint link;
+ if (ivorbisfile->eos)
+ return;
+
/* this function needs to go first since you don't want to be messing
* with an unset vf ;) */
if (ivorbisfile->restart) {
+
ivorbisfile->offset = 0;
ivorbisfile->total_bytes = 0;
ivorbisfile->may_eos = FALSE;
- ivorbisfile->vf.seekable = gst_bytestream_seek (ivorbisfile->bs, 0,
- GST_SEEK_METHOD_SET);
+ ivorbisfile->adapterOffset = 0;
GST_DEBUG ("ivorbisfile: seekable: %s\n",
ivorbisfile->vf.seekable ? "yes" : "no");
/* open our custom ivorbisfile data object with the callbacks we provide */
if (ov_open_callbacks (ivorbisfile, &ivorbisfile->vf, NULL, 0,
ivorbisfile_ov_callbacks) < 0) {
- GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), (NULL));
+ GST_ELEMENT_ERROR (ivorbisfile, STREAM, DECODE, (NULL), (NULL));
return;
}
ivorbisfile->need_discont = TRUE;
GST_BUFFER_DATA (outbuf) = g_malloc (4096);
GST_BUFFER_SIZE (outbuf) = 4096;
+ ret = ov_read (&ivorbisfile->vf,
+ (char *) GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf), &link);
+
/* get current time for discont and buffer timestamp */
time = (GstClockTime) (ov_time_tell (&ivorbisfile->vf) * GST_SECOND);
- ret = ov_read (&ivorbisfile->vf,
- GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf), &link);
-
if (ret == 0) {
GST_DEBUG ("eos");
/* send EOS event */
- /*ov_clear (&ivorbisfile->vf); */
+
ivorbisfile->restart = TRUE;
gst_buffer_unref (outbuf);
/* if the pad is not usable, don't push it out */
- if (GST_PAD_IS_USABLE (ivorbisfile->srcpad)) {
- gst_pad_push (ivorbisfile->srcpad,
- GST_DATA (gst_event_new (GST_EVENT_EOS)));
- }
- gst_element_set_eos (element);
+ gst_pad_push_event (ivorbisfile->srcpad, gst_event_new_eos ());
+
return;
} else if (ret < 0) {
g_warning ("ivorbisfile: decoding error");
return;
} else {
if (ivorbisfile->need_discont) {
- GstEvent *discont;
+ GstEvent *event;
ivorbisfile->need_discont = FALSE;
- /* if the pad is not usable, don't push it out */
- if (GST_PAD_IS_USABLE (ivorbisfile->srcpad)) {
- /* get stream stats */
- samples = (gint64) (ov_pcm_tell (&ivorbisfile->vf));
+ /* get stream stats */
+ samples = (gint64) (ov_pcm_tell (&ivorbisfile->vf));
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time,
- GST_FORMAT_DEFAULT, samples, NULL);
+ event =
+ gst_event_new_newsegment (FALSE, 1.0, GST_FORMAT_TIME, time,
+ GST_CLOCK_TIME_NONE, 0);
+
+ gst_pad_push_event (ivorbisfile->srcpad, event);
- gst_pad_push (ivorbisfile->srcpad, GST_DATA (discont));
- }
}
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ivorbisfile->srcpad));
+
GST_BUFFER_SIZE (outbuf) = ret;
- GST_BUFFER_TIMESTAMP (outbuf) = time;
+ /* FIX ME TO SET RIGHT TIMESTAMP
+ gint bufsize = ret / (ivorbisfile->width / 8);
+ GST_BUFFER_TIMESTAMP (outbuf) = time;
+ GST_BUFFER_DURATION (outbuf) = GST_SECOND * bufsize / (ivorbisfile->rate * ivorbisfile->channels);
+ */
+
ivorbisfile->may_eos = TRUE;
ivorbisfile->total_bytes += GST_BUFFER_SIZE (outbuf);
}
- if (GST_PAD_IS_USABLE (ivorbisfile->srcpad))
- gst_pad_push (ivorbisfile->srcpad, GST_DATA (outbuf));
- else
- gst_buffer_unref (outbuf);
- }
-}
-
-static const GstFormat *
-gst_ivorbisfile_get_formats (GstPad * pad)
-{
- static GstFormat src_formats[] = {
- GST_FORMAT_TIME,
- GST_FORMAT_BYTES,
- GST_FORMAT_DEFAULT,
- 0,
- 0
- };
- static GstFormat sink_formats[] = {
- GST_FORMAT_TIME,
- GST_FORMAT_BYTES,
- 0,
- 0
- };
+ gst_pad_push (ivorbisfile->srcpad, outbuf);
- src_formats[3] = logical_stream_format;
- sink_formats[2] = logical_stream_format;
+ }
- return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
}
static gboolean
Ivorbisfile *ivorbisfile;
vorbis_info *vi;
- ivorbisfile = GST_IVORBISFILE (gst_pad_get_parent (pad));
+ ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad));
vi = ov_info (&ivorbisfile->vf, -1);
bytes_per_sample = vi->channels * 2;
}
static gboolean
+gst_ivorbisfile_sink_query (GstPad * pad, GstQuery * query)
+{
+ gboolean res;
+
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_CONVERT:
+ {
+ GstFormat src_fmt, dest_fmt;
+ gint64 src_val, dest_val;
+
+ /* peel off input */
+ gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
+ if ((res = gst_ivorbisfile_sink_convert (pad, src_fmt, src_val,
+ &dest_fmt, &dest_val))) {
+ gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
+ }
+ break;
+ }
+ default:
+ res = FALSE;
+ break;
+ }
+ return res;
+}
+
+static gboolean
gst_ivorbisfile_sink_convert (GstPad * pad,
GstFormat src_format, gint64 src_value,
GstFormat * dest_format, gint64 * dest_value)
gboolean res = TRUE;
Ivorbisfile *ivorbisfile;
- ivorbisfile = GST_IVORBISFILE (gst_pad_get_parent (pad));
+ ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad));
switch (src_format) {
case GST_FORMAT_BYTES:
}
static const GstQueryType *
-gst_ivorbisfile_get_query_types (GstPad * pad)
+gst_ivorbisfile_get_sink_query_types (GstPad * pad)
+{
+ static const GstQueryType types[] = {
+ GST_QUERY_CONVERT,
+ 0
+ };
+
+ return types;
+}
+
+static const GstQueryType *
+gst_ivorbisfile_get_src_query_types (GstPad * pad)
{
static const GstQueryType types[] = {
- GST_QUERY_TOTAL,
GST_QUERY_POSITION,
+ GST_QUERY_DURATION,
+ GST_QUERY_CONVERT,
0
};
/* handles queries for location in the stream in the requested format */
static gboolean
-gst_ivorbisfile_src_query (GstPad * pad, GstQueryType type,
- GstFormat * format, gint64 * value)
+gst_ivorbisfile_src_query (GstPad * pad, GstQuery * query)
{
gboolean res = TRUE;
Ivorbisfile *ivorbisfile;
vorbis_info *vi;
- ivorbisfile = GST_IVORBISFILE (gst_pad_get_parent (pad));
+ ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad));
vi = ov_info (&ivorbisfile->vf, -1);
- switch (type) {
- case GST_QUERY_TOTAL:
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_POSITION:
{
- switch (*format) {
+
+ GstFormat format;
+ GstFormat rformat = GST_FORMAT_TIME;
+ gint64 cur;
+ GstPad *peer;
+
+ /* save requested format */
+ gst_query_parse_position (query, &format, NULL);
+
+ /* query peer for current position in time */
+ gst_query_set_position (query, GST_FORMAT_TIME, -1);
+
+ if ((peer = gst_pad_get_peer (ivorbisfile->sinkpad)) == NULL)
+ goto error;
+
+ if (!gst_pad_query_position (peer, &rformat, &cur)) {
+ GST_LOG_OBJECT (ivorbisfile, "query on peer pad failed");
+ gst_object_unref (peer);
+ goto error;
+ }
+ gst_object_unref (peer);
+
+ if (format != rformat) {
+ gst_ivorbisfile_src_convert (pad, rformat, cur, &format, &cur);
+ }
+
+ switch (format) {
case GST_FORMAT_DEFAULT:
if (ivorbisfile->vf.seekable)
- *value = ov_pcm_total (&ivorbisfile->vf, -1);
+ cur = ov_pcm_tell (&ivorbisfile->vf);
else
- return FALSE;
+ cur = ivorbisfile->total_bytes / (vi->channels * 2);
break;
- case GST_FORMAT_BYTES:
+ case GST_FORMAT_TIME:
if (ivorbisfile->vf.seekable)
- *value = ov_pcm_total (&ivorbisfile->vf, -1) * vi->channels * 2;
+ cur = (gint64) (ov_time_tell (&ivorbisfile->vf) * GST_SECOND);
else
- return FALSE;
+ cur = ivorbisfile->total_bytes * GST_SECOND
+ / (vi->rate * vi->channels * 2);
break;
- case GST_FORMAT_TIME:
+ case GST_FORMAT_BYTES:
if (ivorbisfile->vf.seekable)
- *value =
- (gint64) (ov_time_total (&ivorbisfile->vf, -1) * GST_SECOND);
+ cur = ov_pcm_tell (&ivorbisfile->vf) * vi->channels * 2;
else
- return FALSE;
+ cur = ivorbisfile->total_bytes;
break;
default:
- if (*format == logical_stream_format) {
+ if (format == logical_stream_format) {
if (ivorbisfile->vf.seekable)
- *value = ivorbisfile->vf.links;
+ cur = ivorbisfile->current_link;
else
return FALSE;
} else
res = FALSE;
break;
}
+
+ gst_query_set_position (query, format, cur);
+
break;
}
- case GST_QUERY_POSITION:
- switch (*format) {
- case GST_FORMAT_TIME:
+ case GST_QUERY_DURATION:
+ {
+
+ GstFormat format;
+ GstFormat rformat = GST_FORMAT_TIME;
+ gint64 cur;
+ GstPad *peer;
+
+ /* save requested format */
+ gst_query_parse_position (query, &format, NULL);
+
+ /* query peer for current position in time */
+ gst_query_set_position (query, GST_FORMAT_TIME, -1);
+
+ if ((peer = gst_pad_get_peer (ivorbisfile->sinkpad)) == NULL)
+ goto error;
+
+ if (!gst_pad_query_position (peer, &rformat, &cur)) {
+ GST_LOG_OBJECT (ivorbisfile, "query on peer pad failed");
+ gst_object_unref (peer);
+ goto error;
+ }
+ gst_object_unref (peer);
+
+ if (format != rformat) {
+ gst_ivorbisfile_src_convert (pad, rformat, cur, &format, &cur);
+ }
+
+ switch (format) {
+ case GST_FORMAT_DEFAULT:
if (ivorbisfile->vf.seekable)
- *value = (gint64) (ov_time_tell (&ivorbisfile->vf) * GST_SECOND);
+ cur = ov_pcm_total (&ivorbisfile->vf, -1);
else
- *value = ivorbisfile->total_bytes * GST_SECOND
- / (vi->rate * vi->channels * 2);
+ return FALSE;
break;
case GST_FORMAT_BYTES:
if (ivorbisfile->vf.seekable)
- *value = ov_pcm_tell (&ivorbisfile->vf) * vi->channels * 2;
+ cur = ov_pcm_total (&ivorbisfile->vf, -1) * vi->channels * 2;
else
- *value = ivorbisfile->total_bytes;
+ return FALSE;
break;
- case GST_FORMAT_DEFAULT:
+ case GST_FORMAT_TIME:
if (ivorbisfile->vf.seekable)
- *value = ov_pcm_tell (&ivorbisfile->vf);
+ cur = (gint64) (ov_time_total (&ivorbisfile->vf, -1) * GST_SECOND);
else
- *value = ivorbisfile->total_bytes / (vi->channels * 2);
+ return FALSE;
break;
default:
- if (*format == logical_stream_format) {
+ if (format == logical_stream_format) {
if (ivorbisfile->vf.seekable)
- *value = ivorbisfile->current_link;
+ cur = ivorbisfile->vf.links;
else
return FALSE;
} else
res = FALSE;
break;
}
+
+ gst_query_set_position (query, format, cur);
+
+ break;
+ }
+ case GST_QUERY_CONVERT:
+ {
+ GstFormat src_fmt, dest_fmt;
+ gint64 src_val, dest_val;
+
+ /* peel off input */
+ gst_query_parse_convert (query, &src_fmt, &src_val, NULL, NULL);
+ if ((res = gst_ivorbisfile_src_convert (pad, src_fmt, src_val,
+ &dest_fmt, &dest_val))) {
+ gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
+ }
break;
+ }
default:
res = FALSE;
break;
}
return res;
+
+error:
+
+ return FALSE;
+
}
-static const GstEventMask *
-gst_ivorbisfile_get_event_masks (GstPad * pad)
+
+static gboolean
+gst_ivorbisfile_sink_event (GstPad * pad, GstEvent * event)
{
- static const GstEventMask masks[] = {
- {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_ACCURATE},
- {0,}
- };
- return masks;
+ Ivorbisfile *ivorbisfile;
+
+ ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ GST_DEBUG ("eos");
+ ov_clear (&ivorbisfile->vf);
+ ivorbisfile->eos = TRUE;
+ break;
+ case GST_EVENT_NEWSEGMENT:
+ GST_DEBUG ("discont");
+ ivorbisfile->need_discont = TRUE;
+ default:
+ break;
+ }
+
+ return gst_pad_event_default (pad, event);
}
+
/* handle events on src pad */
static gboolean
gst_ivorbisfile_src_event (GstPad * pad, GstEvent * event)
gint64 offset;
vorbis_info *vi;
GstFormat format;
+ GstSeekFlags flags;
GST_DEBUG ("ivorbisfile: handling seek event on pad %s:%s",
GST_DEBUG_PAD_NAME (pad));
return FALSE;
}
- offset = GST_EVENT_SEEK_OFFSET (event);
- format = GST_EVENT_SEEK_FORMAT (event);
+ gst_event_parse_seek (event, NULL, &format, &flags, NULL, &offset, NULL,
+ NULL);
switch (format) {
case GST_FORMAT_TIME:
ivorbisfile->seek_pending = TRUE;
ivorbisfile->seek_value = offset;
ivorbisfile->seek_format = format;
- ivorbisfile->seek_accurate = GST_EVENT_SEEK_FLAGS (event)
- & GST_SEEK_FLAG_ACCURATE;
+ ivorbisfile->seek_accurate = flags & GST_SEEK_FLAG_ACCURATE;
break;
case GST_FORMAT_BYTES:
vi = ov_info (&ivorbisfile->vf, -1);
ivorbisfile->seek_pending = TRUE;
ivorbisfile->seek_value = offset;
ivorbisfile->seek_format = format;
- ivorbisfile->seek_accurate = GST_EVENT_SEEK_FLAGS (event)
- & GST_SEEK_FLAG_ACCURATE;
+ ivorbisfile->seek_accurate = flags & GST_SEEK_FLAG_ACCURATE;
break;
default:
if (format == logical_stream_format) {
ivorbisfile->seek_pending = TRUE;
ivorbisfile->seek_value = offset;
ivorbisfile->seek_format = format;
- ivorbisfile->seek_accurate = GST_EVENT_SEEK_FLAGS (event)
- & GST_SEEK_FLAG_ACCURATE;
+ ivorbisfile->seek_accurate = flags & GST_SEEK_FLAG_ACCURATE;
} else {
GST_DEBUG ("unhandled seek format");
res = FALSE;
static GstStateChangeReturn
gst_ivorbisfile_change_state (GstElement * element, GstStateChange transition)
{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
Ivorbisfile *ivorbisfile = GST_IVORBISFILE (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
+ /* fall through */
case GST_STATE_CHANGE_READY_TO_PAUSED:
ivorbisfile->restart = TRUE;
- ivorbisfile->bs = gst_bytestream_new (ivorbisfile->sinkpad);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
ivorbisfile->eos = FALSE;
+ break;
+ default:
+ break;
+ }
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
ov_clear (&ivorbisfile->vf);
- gst_bytestream_destroy (ivorbisfile->bs);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
default:
break;
}
- if (GST_ELEMENT_CLASS (parent_class)->change_state)
- return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
- return GST_STATE_CHANGE_SUCCESS;
+
+ return ret;
}
static void