Ported to 0.9. Some issues to be solved yet: 1- set correct timestamps 2- seg fault when eos 3- seek is now disabled

Original commit message from CVS:
Ported to 0.9. Some issues to be solved yet:
1- set correct timestamps
2- seg fault when eos
3- seek is now disabled
This commit is contained in:
Edgard Lima 2005-11-08 13:55:13 +00:00
parent 7a50084e34
commit 5df1c827fb
6 changed files with 385 additions and 206 deletions

View file

@ -1,3 +1,15 @@
2005-11-08 Edgard Lima <edgard.lima@indt.org.br>
configure.ac:
PORTED_09:
ext/Makefile.am:
ext/ivorbis/vorbis.c:
ext/ivorbis/vorbisfile.c:
Ported to 0.9. Some issues to be solved yet:
1- set correct timestamps
2- seg fault when eos
3- seek is now disabled
2005-11-06 Julien MOUTTE <julien@moutte.net>
* examples/Makefile.am: Cleanup non existing

View file

@ -1,6 +1,7 @@
When porting a plugin start with 0.8 CVS head, not the old code in this module. There are many bugfixes which have gone into 0.8 which you want to keep.
List of ported plugins (update when you commit a ported plugin):
ivorbis (alima)
gsmdec (alima)
sdl (alima)
speed (fcarvalho)

View file

@ -409,6 +409,19 @@ GST_CHECK_FEATURE(SDL, [SDL plug-in], sdlvideosink, [
fi
])
dnl *** ivorbis ***
dnl AM_PATH_IVORBIS only takes two options
translit(dnm, m, l) AM_CONDITIONAL(USE_IVORBIS, true)
GST_CHECK_FEATURE(IVORBIS, [integer vorbis plug-in], ivorbisdec, [
IVORBIS_LIBS=
IVORBIS_CFLAGS=
AC_CHECK_LIB(vorbisidec, vorbis_block_init,
[IVORBIS_LIBS=-lvorbisidec
HAVE_IVORBIS=yes],
HAVE_IVORBIS=no)
AC_SUBST(IVORBIS_LIBS)
AC_SUBST(IVORBIS_CFLAGS)
])
dnl *** gsm ***
translit(dnm, m, l) AM_CONDITIONAL(USE_GSM, true)
@ -496,6 +509,7 @@ ext/Makefile
ext/directfb/Makefile
ext/faac/Makefile
ext/faad/Makefile
ext/ivorbis/Makefile
ext/gsm/Makefile
ext/sdl/Makefile
docs/Makefile

View file

@ -76,11 +76,11 @@ endif
HERMES_DIR=
# endif
# if USE_IVORBIS
# IVORBIS_DIR=ivorbis
# else
IVORBIS_DIR=
# endif
if USE_IVORBIS
IVORBIS_DIR=ivorbis
else
IVORBIS_DIR=
endif
# if USE_JACK
# JACK_DIR=jack

View file

@ -30,9 +30,6 @@ extern GType ivorbisfile_get_type (void);
static gboolean
plugin_init (GstPlugin * plugin)
{
if (!gst_library_load ("gstbytestream"))
return FALSE;
if (!gst_element_register (plugin, "tremor", GST_RANK_PRIMARY,
ivorbisfile_get_type ()))
return FALSE;

View file

@ -24,20 +24,20 @@
#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;
@ -48,7 +48,8 @@ struct _Ivorbisfile
GstElement element;
GstPad *sinkpad, *srcpad;
GstByteStream *bs;
GstAdapter *adapter;
guint64 adapterOffset;
OggVorbis_File vf;
gint current_link;
@ -65,6 +66,10 @@ struct _Ivorbisfile
guint64 total_bytes;
guint64 offset;
gint rate;
gint channels;
gint width;
GstCaps *metadata;
GstCaps *streaminfo;
};
@ -109,31 +114,38 @@ static void gst_ivorbisfile_init (Ivorbisfile * ivorbisfile);
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 gboolean
gst_ivorbisfile_sink_activate_pull (GstPad * sinkpad, gboolean active);
static void gst_ivorbisfile_loop (GstPad * pad);
static GstElementClass *parent_class = NULL;
//static guint gst_ivorbisfile_signals[LAST_SIGNAL] = { 0 };
static GstFormat logical_stream_format;
GType
@ -230,6 +242,9 @@ gst_ivorbisfile_class_init (IvorbisfileClass * klass)
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));
@ -237,8 +252,6 @@ gst_ivorbisfile_class_init (IvorbisfileClass * klass)
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;
}
@ -249,26 +262,27 @@ gst_ivorbisfile_init (Ivorbisfile * ivorbisfile)
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;
@ -277,6 +291,11 @@ gst_ivorbisfile_init (Ivorbisfile * ivorbisfile)
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
@ -285,15 +304,15 @@ gst_ivorbisfile_init (Ivorbisfile * 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;
@ -302,50 +321,25 @@ gst_ivorbisfile_read (void *ptr, size_t size, size_t nmemb, void *datasource)
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;
@ -357,24 +351,22 @@ gst_ivorbisfile_seek (void *datasource, int64_t offset, int whence)
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;
}
@ -392,7 +384,7 @@ gst_ivorbisfile_tell (void *datasource)
Ivorbisfile *ivorbisfile = GST_IVORBISFILE (datasource);
long result;
result = gst_bytestream_tell (ivorbisfile->bs);
result = ivorbisfile->adapterOffset;
GST_DEBUG ("tell %ld", result);
@ -513,40 +505,89 @@ gst_ivorbisfile_new_link (Ivorbisfile * ivorbisfile, gint link)
"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 void
gst_ivorbisfile_loop (GstElement * element)
static gboolean
gst_ivorbisfile_sink_activate (GstPad * sinkpad)
{
Ivorbisfile *ivorbisfile = GST_IVORBISFILE (element);
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 (GstPad * pad)
{
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;
@ -615,24 +656,21 @@ gst_ivorbisfile_loop (GstElement * element)
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");
@ -640,24 +678,30 @@ gst_ivorbisfile_loop (GstElement * element)
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;
@ -665,34 +709,10 @@ gst_ivorbisfile_loop (GstElement * element)
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);
gst_pad_push (ivorbisfile->srcpad, 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
};
src_formats[3] = logical_stream_format;
sink_formats[2] = logical_stream_format;
return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
}
static gboolean
@ -706,7 +726,7 @@ gst_ivorbisfile_src_convert (GstPad * pad,
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;
@ -803,6 +823,32 @@ gst_ivorbisfile_src_convert (GstPad * pad,
return res;
}
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,
@ -811,7 +857,7 @@ gst_ivorbisfile_sink_convert (GstPad * pad,
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:
@ -851,11 +897,23 @@ gst_ivorbisfile_sink_convert (GstPad * pad,
}
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
};
@ -864,103 +922,194 @@ gst_ivorbisfile_get_query_types (GstPad * pad)
/* 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;
break;
case GST_FORMAT_BYTES:
if (ivorbisfile->vf.seekable)
*value = ov_pcm_total (&ivorbisfile->vf, -1) * vi->channels * 2;
else
return FALSE;
cur = ivorbisfile->total_bytes / (vi->channels * 2);
break;
case GST_FORMAT_TIME:
if (ivorbisfile->vf.seekable)
*value =
(gint64) (ov_time_total (&ivorbisfile->vf, -1) * GST_SECOND);
cur = (gint64) (ov_time_tell (&ivorbisfile->vf) * GST_SECOND);
else
return FALSE;
break;
default:
if (*format == logical_stream_format) {
if (ivorbisfile->vf.seekable)
*value = ivorbisfile->vf.links;
else
return FALSE;
} else
res = FALSE;
break;
}
break;
}
case GST_QUERY_POSITION:
switch (*format) {
case GST_FORMAT_TIME:
if (ivorbisfile->vf.seekable)
*value = (gint64) (ov_time_tell (&ivorbisfile->vf) * GST_SECOND);
else
*value = ivorbisfile->total_bytes * GST_SECOND
cur = ivorbisfile->total_bytes * GST_SECOND
/ (vi->rate * vi->channels * 2);
break;
case GST_FORMAT_BYTES:
if (ivorbisfile->vf.seekable)
*value = ov_pcm_tell (&ivorbisfile->vf) * vi->channels * 2;
cur = ov_pcm_tell (&ivorbisfile->vf) * vi->channels * 2;
else
*value = ivorbisfile->total_bytes;
break;
case GST_FORMAT_DEFAULT:
if (ivorbisfile->vf.seekable)
*value = ov_pcm_tell (&ivorbisfile->vf);
else
*value = ivorbisfile->total_bytes / (vi->channels * 2);
cur = ivorbisfile->total_bytes;
break;
default:
if (*format == logical_stream_format) {
if (format == logical_stream_format) {
if (ivorbisfile->vf.seekable)
*value = ivorbisfile->current_link;
cur = ivorbisfile->current_link;
else
return FALSE;
} else
res = FALSE;
break;
}
gst_query_set_position (query, format, cur);
break;
}
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)
cur = ov_pcm_total (&ivorbisfile->vf, -1);
else
return FALSE;
break;
case GST_FORMAT_BYTES:
if (ivorbisfile->vf.seekable)
cur = ov_pcm_total (&ivorbisfile->vf, -1) * vi->channels * 2;
else
return FALSE;
break;
case GST_FORMAT_TIME:
if (ivorbisfile->vf.seekable)
cur = (gint64) (ov_time_total (&ivorbisfile->vf, -1) * GST_SECOND);
else
return FALSE;
break;
default:
if (format == logical_stream_format) {
if (ivorbisfile->vf.seekable)
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)
@ -976,6 +1125,7 @@ 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));
@ -985,16 +1135,15 @@ gst_ivorbisfile_src_event (GstPad * pad, GstEvent * event)
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);
@ -1009,16 +1158,14 @@ gst_ivorbisfile_src_event (GstPad * pad, GstEvent * event)
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;
@ -1040,31 +1187,39 @@ done:
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