summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--configure.ac15
-rw-r--r--ext/Makefile.am9
-rw-r--r--ext/flac/Makefile.am3
-rw-r--r--ext/flac/gstflac.c14
-rw-r--r--ext/flac/gstflacdec.c368
-rw-r--r--ext/flac/gstflacdec.h3
7 files changed, 230 insertions, 198 deletions
diff --git a/ChangeLog b/ChangeLog
index 9462e57d..c77cc7c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2005-08-22 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+
+ * configure.ac:
+ * ext/Makefile.am:
+ * ext/flac/Makefile.am:
+ * ext/flac/gstflac.c: (plugin_init):
+ * ext/flac/gstflacdec.c: (flacdec_get_type), (gst_flacdec_init),
+ (gst_flacdec_update_metadata), (gst_flacdec_seek),
+ (gst_flacdec_tell), (gst_flacdec_length), (gst_flacdec_read),
+ (gst_flacdec_write), (gst_flacdec_loop),
+ (gst_flacdec_get_src_query_types), (gst_flacdec_src_query),
+ (gst_flacdec_src_event), (gst_flacdec_sink_activate),
+ (gst_flacdec_sink_activate_pull), (gst_flacdec_change_state):
+ * ext/flac/gstflacdec.h:
+ Port flacdec (seeking is still slow'ish).
+
2005-08-22 Owen Fraser-Green <owen@discobabe.net>
* gst/realmedia/rmdemux.c:
diff --git a/configure.ac b/configure.ac
index 39efc328..cbf2b272 100644
--- a/configure.ac
+++ b/configure.ac
@@ -411,6 +411,20 @@ return 0;
AC_SUBST(FAAD_LIBS)
])
+dnl *** FLAC ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_FLAC, true)
+GST_CHECK_FEATURE(FLAC, [FLAC lossless audio], flacenc flacdec, [
+ GST_CHECK_LIBHEADER(FLAC, FLAC, FLAC__seekable_stream_encoder_new, -lm, FLAC/all.h, FLAC_LIBS="-lFLAC -lm")
+ dnl API change in FLAC 1.1.1, so require that...
+ if test x$HAVE_FLAC = xyes; then
+ AC_CHECK_DECL(FLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR,
+ HAVE_FLAC="yes", HAVE_FLAC="no", [
+#include <FLAC/seekable_stream_encoder.h>
+ ])
+ fi
+ AC_SUBST(FLAC_LIBS)
+])
+
dnl *** lame ***
translit(dnm, m, l) AM_CONDITIONAL(USE_LAME, true)
GST_CHECK_FEATURE(LAME, [lame mp3 encoder library], lame, [
@@ -653,6 +667,7 @@ sys/oss/Makefile
ext/Makefile
ext/aalib/Makefile
ext/dv/Makefile
+ext/flac/Makefile
ext/gconf/Makefile
ext/lame/Makefile
ext/libcaca/Makefile
diff --git a/ext/Makefile.am b/ext/Makefile.am
index 4fb0317a..7f1ea76a 100644
--- a/ext/Makefile.am
+++ b/ext/Makefile.am
@@ -118,11 +118,11 @@ endif
## FESTIVAL_DIR=
## endif
-# if USE_FLAC
-# FLAC_DIR=flac
-# else
+if USE_FLAC
+FLAC_DIR=flac
+else
FLAC_DIR=
-# endif
+endif
if USE_GCONF
GCONF_DIR=gconf
@@ -451,6 +451,7 @@ DIST_SUBDIRS=\
dv \
amrnb \
faad \
+ flac \
mpeg2dec \
jpeg \
libpng \
diff --git a/ext/flac/Makefile.am b/ext/flac/Makefile.am
index be66e70b..191e2ee5 100644
--- a/ext/flac/Makefile.am
+++ b/ext/flac/Makefile.am
@@ -1,7 +1,8 @@
plugin_LTLIBRARIES = libgstflac.la
-libgstflac_la_SOURCES = gstflac.c gstflacenc.c gstflacdec.c gstflactag.c
+libgstflac_la_SOURCES = gstflac.c gstflacdec.c
+#gstflacenc.c gstflactag.c
libgstflac_la_CFLAGS = $(GST_CFLAGS) -I$(top_srcdir)
libgstflac_la_LIBADD = $(FLAC_LIBS)
libgstflac_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
diff --git a/ext/flac/gstflac.c b/ext/flac/gstflac.c
index 9432713f..28aa4e11 100644
--- a/ext/flac/gstflac.c
+++ b/ext/flac/gstflac.c
@@ -30,25 +30,19 @@
static gboolean
plugin_init (GstPlugin * plugin)
{
- if (!gst_library_load ("gstbytestream"))
- return FALSE;
-
- /* we need the gsttags plugin for metadata querying */
- if (!gst_plugin_load ("gsttags"))
- return FALSE;
-
+#if 0
if (!gst_element_register (plugin, "flacenc", GST_RANK_NONE,
GST_TYPE_FLACENC))
return FALSE;
-
+#endif
if (!gst_element_register (plugin, "flacdec", GST_RANK_PRIMARY,
GST_TYPE_FLACDEC))
return FALSE;
-
+#if 0
if (!gst_element_register (plugin, "flactag", GST_RANK_PRIMARY,
gst_flac_tag_get_type ()))
return FALSE;
-
+#endif
return TRUE;
}
diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c
index 480b8033..8289bf4b 100644
--- a/ext/flac/gstflacdec.c
+++ b/ext/flac/gstflacdec.c
@@ -22,14 +22,16 @@
#endif
#include <string.h>
-/*#define DEBUG_ENABLED */
#include "gstflacdec.h"
#include <gst/gsttaginterface.h>
-#include <gst/tag/tag.h>
+//#include <gst/tag/tag.h>
#include "flac_compat.h"
+GST_DEBUG_CATEGORY_STATIC (flacdec_debug);
+#define GST_CAT_DEFAULT flacdec_debug
+
static GstPadTemplate *src_template, *sink_template;
/* elementfactory information */
@@ -40,34 +42,21 @@ GstElementDetails flacdec_details = {
"Wim Taymans <wim.taymans@chello.be>",
};
-/* FlacDec signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0,
- ARG_METADATA
-};
-
static void gst_flacdec_base_init (gpointer g_class);
static void gst_flacdec_class_init (FlacDecClass * klass);
static void gst_flacdec_init (FlacDec * flacdec);
static void gst_flacdec_finalize (GObject * object);
-static void gst_flacdec_loop (GstElement * element);
+static void gst_flacdec_loop (GstPad * pad);
static GstElementStateReturn gst_flacdec_change_state (GstElement * element);
-static const GstFormat *gst_flacdec_get_src_formats (GstPad * pad);
+static const GstQueryType *gst_flacdec_get_src_query_types (GstPad * pad);
+static gboolean gst_flacdec_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_flacdec_convert_src (GstPad * pad, GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
-static const GstQueryType *gst_flacdec_get_src_query_types (GstPad * pad);
-static gboolean gst_flacdec_src_query (GstPad * pad, GstQueryType type,
- GstFormat * format, gint64 * value);
-static const GstEventMask *gst_flacdec_get_src_event_masks (GstPad * pad);
static gboolean gst_flacdec_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_flacdec_sink_activate (GstPad * sinkpad);
+static gboolean gst_flacdec_sink_activate_pull (GstPad * sinkpad,
+ gboolean active);
static FLAC__SeekableStreamDecoderReadStatus
gst_flacdec_read (const FLAC__SeekableStreamDecoder * decoder,
@@ -116,6 +105,8 @@ flacdec_get_type (void)
flacdec_type =
g_type_register_static (GST_TYPE_ELEMENT, "FlacDec", &flacdec_info, 0);
+
+ GST_DEBUG_CATEGORY_INIT (flacdec_debug, "flacdec", 0, "flac decoder");
}
return flacdec_type;
}
@@ -178,21 +169,18 @@ static void
gst_flacdec_init (FlacDec * flacdec)
{
flacdec->sinkpad = gst_pad_new_from_template (sink_template, "sink");
+ gst_pad_set_activate_function (flacdec->sinkpad, gst_flacdec_sink_activate);
+ gst_pad_set_activatepull_function (flacdec->sinkpad,
+ gst_flacdec_sink_activate_pull);
gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->sinkpad);
- gst_pad_set_convert_function (flacdec->sinkpad, NULL);
- gst_element_set_loop_function (GST_ELEMENT (flacdec), gst_flacdec_loop);
flacdec->srcpad = gst_pad_new_from_template (src_template, "src");
- gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->srcpad);
- gst_pad_set_formats_function (flacdec->srcpad, gst_flacdec_get_src_formats);
- gst_pad_set_convert_function (flacdec->srcpad, gst_flacdec_convert_src);
gst_pad_set_query_type_function (flacdec->srcpad,
gst_flacdec_get_src_query_types);
gst_pad_set_query_function (flacdec->srcpad, gst_flacdec_src_query);
- gst_pad_set_event_mask_function (flacdec->srcpad,
- gst_flacdec_get_src_event_masks);
gst_pad_set_event_function (flacdec->srcpad, gst_flacdec_src_event);
- gst_pad_use_explicit_caps (flacdec->srcpad);
+ gst_pad_use_fixed_caps (flacdec->srcpad);
+ gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->srcpad);
flacdec->decoder = FLAC__seekable_stream_decoder_new ();
flacdec->total_samples = 0;
@@ -262,7 +250,7 @@ gst_flacdec_update_metadata (FlacDec * flacdec,
value = NULL;
GST_DEBUG ("%d tag(s) found", number_of_comments);
for (cursor = 0; cursor < number_of_comments; cursor++) {
- str_ptr = metadata->data.vorbis_comment.comments[cursor].entry;
+ str_ptr = (gchar *) metadata->data.vorbis_comment.comments[cursor].entry;
str_len = metadata->data.vorbis_comment.comments[cursor].length;
p_value = g_strstr_len (str_ptr, str_len, "=");
if (p_value) {
@@ -270,7 +258,7 @@ gst_flacdec_update_metadata (FlacDec * flacdec,
value = g_strndup (p_value + 1, str_ptr + str_len - p_value - 1);
GST_DEBUG ("%s : %s", name, value);
- gst_vorbis_tag_add (list, name, value);
+ //gst_vorbis_tag_add (list, name, value);
g_free (name);
g_free (value);
}
@@ -278,10 +266,8 @@ gst_flacdec_update_metadata (FlacDec * flacdec,
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_AUDIO_CODEC, "FLAC", NULL);
- gst_element_found_tags (GST_ELEMENT (flacdec), list);
- if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
- gst_pad_push (flacdec->srcpad, GST_DATA (gst_event_new_tag (list)));
- }
+ gst_element_found_tags_for_pad (GST_ELEMENT (flacdec), flacdec->srcpad, list);
+
return TRUE;
}
@@ -342,9 +328,8 @@ gst_flacdec_seek (const FLAC__SeekableStreamDecoder * decoder,
flacdec = GST_FLACDEC (client_data);
GST_DEBUG ("seek %" G_GINT64_FORMAT, position);
- if (!gst_bytestream_seek (flacdec->bs, position, GST_SEEK_METHOD_SET)) {
- return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
- }
+ flacdec->offset = position;
+
return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
}
@@ -356,9 +341,7 @@ gst_flacdec_tell (const FLAC__SeekableStreamDecoder * decoder,
flacdec = GST_FLACDEC (client_data);
- *position = gst_bytestream_tell (flacdec->bs);
- if (*position == -1)
- return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
+ *position = flacdec->offset;
GST_DEBUG ("tell %" G_GINT64_FORMAT, *position);
@@ -370,12 +353,20 @@ gst_flacdec_length (const FLAC__SeekableStreamDecoder * decoder,
FLAC__uint64 * length, void *client_data)
{
FlacDec *flacdec;
+ GstFormat fmt = GST_FORMAT_BYTES;
+ gint64 len;
+ GstPad *peer;
flacdec = GST_FLACDEC (client_data);
- *length = gst_bytestream_length (flacdec->bs);
- if (*length == -1)
+ if (!(peer = gst_pad_get_peer (flacdec->sinkpad)))
return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
+ gst_pad_query_position (peer, &fmt, NULL, &len);
+ gst_object_unref (peer);
+ if (fmt != GST_FORMAT_BYTES || len == -1)
+ return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
+
+ *length = len;
GST_DEBUG ("length %" G_GINT64_FORMAT, *length);
@@ -398,51 +389,20 @@ gst_flacdec_read (const FLAC__SeekableStreamDecoder * decoder,
FLAC__byte buffer[], unsigned *bytes, void *client_data)
{
FlacDec *flacdec;
- gint insize = 0;
- guint8 *indata;
+ GstBuffer *buf;
flacdec = GST_FLACDEC (client_data);
- //g_print ("read %u\n", *bytes);
+ if (gst_pad_pull_range (flacdec->sinkpad, flacdec->offset, *bytes,
+ &buf) != GST_FLOW_OK)
+ return FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
- while (insize == 0) {
- insize = gst_bytestream_peek_bytes (flacdec->bs, &indata, *bytes);
- if (insize < *bytes) {
- GstEvent *event;
- guint32 avail;
-
- gst_bytestream_get_status (flacdec->bs, &avail, &event);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_EOS:
- GST_DEBUG ("eos");
- flacdec->eos = TRUE;
- gst_event_unref (event);
- if (avail == 0) {
- return 0;
- }
- break;
- case GST_EVENT_DISCONTINUOUS:
- GST_DEBUG ("discont");
-
- /* we are not yet sending the discont, we'll do that in the next write operation */
- flacdec->need_discont = TRUE;
- gst_event_unref (event);
- break;
- default:
- gst_pad_event_default (flacdec->sinkpad, event);
- break;
- }
- if (avail > 0)
- insize = gst_bytestream_peek_bytes (flacdec->bs, &indata, avail);
- else
- insize = 0;
- }
- }
-
- memcpy (buffer, indata, insize);
- *bytes = insize;
- gst_bytestream_flush_fast (flacdec->bs, insize);
+ GST_DEBUG ("Read %d bytes at %" G_GUINT64_FORMAT,
+ GST_BUFFER_SIZE (buf), flacdec->offset);
+ memcpy (buffer, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ *bytes = GST_BUFFER_SIZE (buf);
+ gst_buffer_unref (buf);
+ flacdec->offset += *bytes;
return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
}
@@ -458,6 +418,7 @@ gst_flacdec_write (const FLAC__SeekableStreamDecoder * decoder,
guint channels = frame->header.channels;
guint samples = frame->header.blocksize;
guint j, i;
+ GstFlowReturn ret;
flacdec = GST_FLACDEC (client_data);
@@ -472,68 +433,73 @@ gst_flacdec_write (const FLAC__SeekableStreamDecoder * decoder,
flacdec->total_samples = flacdec->seek_value;
}
- if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
- GST_DEBUG ("send discont");
+ GST_DEBUG ("send discont to %" G_GUINT64_FORMAT, flacdec->seek_value);
- format = GST_FORMAT_TIME;
- gst_pad_convert (flacdec->srcpad, GST_FORMAT_DEFAULT,
- flacdec->total_samples, &format, &time);
- format = GST_FORMAT_BYTES;
- gst_pad_convert (flacdec->srcpad, GST_FORMAT_DEFAULT,
- flacdec->total_samples, &format, &bytes);
- discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time,
- GST_FORMAT_BYTES, bytes,
- GST_FORMAT_DEFAULT, flacdec->total_samples, NULL);
+ format = GST_FORMAT_TIME;
+ gst_flacdec_convert_src (flacdec->srcpad, GST_FORMAT_DEFAULT,
+ flacdec->total_samples, &format, &time);
+ format = GST_FORMAT_BYTES;
+ gst_flacdec_convert_src (flacdec->srcpad, GST_FORMAT_DEFAULT,
+ flacdec->total_samples, &format, &bytes);
+ discont = gst_event_new_newsegment (1.0, GST_FORMAT_TIME, time,
+ GST_CLOCK_TIME_NONE, 0);
- gst_pad_push (flacdec->srcpad, GST_DATA (discont));
- }
+ if (!gst_pad_push_event (flacdec->srcpad, discont))
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if (!GST_PAD_CAPS (flacdec->srcpad)) {
- gst_pad_set_explicit_caps (flacdec->srcpad,
- gst_caps_new_simple ("audio/x-raw-int",
- "endianness", G_TYPE_INT, G_BYTE_ORDER,
- "signed", G_TYPE_BOOLEAN, TRUE,
- "width", G_TYPE_INT, depth,
- "depth", G_TYPE_INT, depth,
- "rate", G_TYPE_INT, frame->header.sample_rate,
- "channels", G_TYPE_INT, channels, NULL));
+ GST_DEBUG ("Negotiating %d Hz @ %d channels",
+ frame->header.sample_rate, channels);
+
+ if (!gst_pad_set_caps (flacdec->srcpad,
+ gst_caps_new_simple ("audio/x-raw-int",
+ "endianness", G_TYPE_INT, G_BYTE_ORDER,
+ "signed", G_TYPE_BOOLEAN, TRUE,
+ "width", G_TYPE_INT, depth,
+ "depth", G_TYPE_INT, depth,
+ "rate", G_TYPE_INT, frame->header.sample_rate,
+ "channels", G_TYPE_INT, channels, NULL)))
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
flacdec->depth = depth;
flacdec->channels = channels;
flacdec->frequency = frame->header.sample_rate;
}
- if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
- outbuf = gst_buffer_new ();
- GST_BUFFER_SIZE (outbuf) = samples * channels * ((depth + 7) >> 3);
- GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
- GST_BUFFER_TIMESTAMP (outbuf) =
- flacdec->total_samples * GST_SECOND / frame->header.sample_rate;
- GST_BUFFER_DURATION (outbuf) =
- samples * GST_SECOND / frame->header.sample_rate;
-
- if (depth == 8) {
- guint8 *outbuffer = (guint8 *) GST_BUFFER_DATA (outbuf);
-
- for (i = 0; i < samples; i++) {
- for (j = 0; j < channels; j++) {
- *outbuffer++ = (guint8) buffer[j][i];
- }
+ gst_pad_alloc_buffer (flacdec->srcpad, flacdec->total_samples,
+ samples * channels * ((depth + 7) >> 3), GST_PAD_CAPS (flacdec->srcpad),
+ &outbuf);
+ GST_BUFFER_TIMESTAMP (outbuf) =
+ flacdec->total_samples * GST_SECOND / frame->header.sample_rate;
+ GST_BUFFER_DURATION (outbuf) =
+ samples * GST_SECOND / frame->header.sample_rate;
+
+ if (depth == 8) {
+ guint8 *outbuffer = (guint8 *) GST_BUFFER_DATA (outbuf);
+
+ for (i = 0; i < samples; i++) {
+ for (j = 0; j < channels; j++) {
+ *outbuffer++ = (guint8) buffer[j][i];
}
- } else if (depth == 16) {
- guint16 *outbuffer = (guint16 *) GST_BUFFER_DATA (outbuf);
+ }
+ } else if (depth == 16) {
+ guint16 *outbuffer = (guint16 *) GST_BUFFER_DATA (outbuf);
- for (i = 0; i < samples; i++) {
- for (j = 0; j < channels; j++) {
- *outbuffer++ = (guint16) buffer[j][i];
- }
+ for (i = 0; i < samples; i++) {
+ for (j = 0; j < channels; j++) {
+ *outbuffer++ = (guint16) buffer[j][i];
}
- } else {
- g_warning ("flacdec: invalid depth %d found\n", depth);
- return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
- gst_pad_push (flacdec->srcpad, GST_DATA (outbuf));
+ } else {
+ g_warning ("flacdec: invalid depth %d found\n", depth);
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+ GST_DEBUG ("Writing %d samples", samples);
+ ret = gst_pad_push (flacdec->srcpad, outbuf);
+ if (ret != GST_FLOW_NOT_LINKED && ret != GST_FLOW_OK) {
+ GST_DEBUG ("Invalid return code");
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
flacdec->total_samples += samples;
@@ -541,12 +507,15 @@ gst_flacdec_write (const FLAC__SeekableStreamDecoder * decoder,
}
static void
-gst_flacdec_loop (GstElement * element)
+gst_flacdec_loop (GstPad * sinkpad)
{
FlacDec *flacdec;
gboolean res;
+ FLAC__SeekableStreamDecoderState s;
- flacdec = GST_FLACDEC (element);
+ flacdec = GST_FLACDEC (GST_OBJECT_PARENT (sinkpad));
+
+ GST_STREAM_LOCK (sinkpad);
GST_DEBUG ("flacdec: entering loop");
if (flacdec->init) {
@@ -557,7 +526,7 @@ gst_flacdec_loop (GstElement * element)
if (res != FLAC__SEEKABLE_STREAM_DECODER_OK) {
GST_ELEMENT_ERROR (flacdec, LIBRARY, INIT, (NULL),
(FLAC__SeekableStreamDecoderStateString[res]));
- return;
+ goto end;
}
/* FLAC__seekable_stream_decoder_process_metadata (flacdec->decoder); */
flacdec->init = FALSE;
@@ -569,6 +538,7 @@ gst_flacdec_loop (GstElement * element)
if (FLAC__seekable_stream_decoder_seek_absolute (flacdec->decoder,
flacdec->seek_value)) {
flacdec->total_samples = flacdec->seek_value;
+ flacdec->need_discont = TRUE;
GST_DEBUG ("seek done");
} else {
GST_DEBUG ("seek failed");
@@ -578,24 +548,35 @@ gst_flacdec_loop (GstElement * element)
GST_DEBUG ("flacdec: processing single");
res = FLAC__seekable_stream_decoder_process_single (flacdec->decoder);
+ if (!res)
+ goto end;
GST_DEBUG ("flacdec: checking for EOS");
- if (FLAC__seekable_stream_decoder_get_state (flacdec->decoder) ==
+ if ((s = FLAC__seekable_stream_decoder_get_state (flacdec->decoder)) ==
FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) {
GstEvent *event;
GST_DEBUG ("flacdec: sending EOS event");
FLAC__seekable_stream_decoder_reset (flacdec->decoder);
- if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
- event = gst_event_new (GST_EVENT_EOS);
- gst_pad_push (flacdec->srcpad, GST_DATA (event));
- }
- gst_element_set_eos (element);
+ event = gst_event_new_eos ();
+ if (!gst_pad_push_event (flacdec->srcpad, event))
+ goto end;
+ } else if (s >= FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR &&
+ s <= FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK) {
+ GST_DEBUG ("Error: %d", s);
+ goto end;
}
GST_DEBUG ("flacdec: _loop end");
-}
+ GST_STREAM_UNLOCK (sinkpad);
+ return;
+end:
+ GST_DEBUG ("pausing");
+ gst_pad_pause_task (sinkpad);
+ GST_STREAM_UNLOCK (sinkpad);
+}
+#if 0
static const GstFormat *
gst_flacdec_get_src_formats (GstPad * pad)
{
@@ -608,6 +589,7 @@ gst_flacdec_get_src_formats (GstPad * pad)
return formats;
}
+#endif
static gboolean
gst_flacdec_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
@@ -676,7 +658,6 @@ static const GstQueryType *
gst_flacdec_get_src_query_types (GstPad * pad)
{
static const GstQueryType types[] = {
- GST_QUERY_TOTAL,
GST_QUERY_POSITION,
0,
};
@@ -685,30 +666,31 @@ gst_flacdec_get_src_query_types (GstPad * pad)
}
static gboolean
-gst_flacdec_src_query (GstPad * pad, GstQueryType type,
- GstFormat * format, gint64 * value)
+gst_flacdec_src_query (GstPad * pad, GstQuery * query)
{
gboolean res = TRUE;
FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
- switch (type) {
- case GST_QUERY_TOTAL:
- {
- guint64 samples;
+ switch (GST_QUERY_TYPE (query)) {
+ case GST_QUERY_POSITION:{
+ gint64 len, pos;
+ GstFormat fmt = GST_FORMAT_TIME;
if (flacdec->stream_samples == 0)
- samples = flacdec->total_samples;
+ len = flacdec->total_samples;
else
- samples = flacdec->stream_samples;
-
- res = gst_pad_convert (flacdec->srcpad,
- GST_FORMAT_DEFAULT, samples, format, value);
+ len = flacdec->stream_samples;
+ pos = flacdec->total_samples;
+
+ if (gst_flacdec_convert_src (flacdec->srcpad,
+ GST_FORMAT_DEFAULT, len, &fmt, &len) &&
+ gst_flacdec_convert_src (flacdec->srcpad,
+ GST_FORMAT_DEFAULT, pos, &fmt, &pos))
+ gst_query_set_position (query, GST_FORMAT_TIME, pos, len);
+ else
+ res = FALSE;
break;
}
- case GST_QUERY_POSITION:
- res = gst_pad_convert (flacdec->srcpad,
- GST_FORMAT_DEFAULT, flacdec->total_samples, format, value);
- break;
default:
res = FALSE;
break;
@@ -717,35 +699,42 @@ gst_flacdec_src_query (GstPad * pad, GstQueryType type,
return res;
}
-static const GstEventMask *
-gst_flacdec_get_src_event_masks (GstPad * pad)
-{
- static const GstEventMask masks[] = {
- {GST_EVENT_SEEK, GST_SEEK_FLAG_ACCURATE},
- {0, 0},
- };
-
- return masks;
-}
-
static gboolean
gst_flacdec_src_event (GstPad * pad, GstEvent * event)
{
gboolean res = TRUE;
FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
- GstFormat format;
switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
+ case GST_EVENT_SEEK:{
+ GstFormat format, seek_fmt;
+ GstSeekType type;
+ gint64 pos;
+
+ gst_event_parse_seek (event, NULL, &seek_fmt, NULL, &type, &pos,
+ NULL, NULL);
+
format = GST_FORMAT_DEFAULT;
- if (gst_pad_convert (flacdec->srcpad,
- GST_EVENT_SEEK_FORMAT (event),
- GST_EVENT_SEEK_OFFSET (event), &format, &flacdec->seek_value))
+ if (type == GST_SEEK_TYPE_SET &&
+ gst_flacdec_convert_src (flacdec->srcpad, seek_fmt, pos,
+ &format, &pos)) {
+ GST_DEBUG ("Initializing seek");
+ g_print ("Grab seek lock\n");
+ gst_pad_push_event (flacdec->srcpad, gst_event_new_flush_start ());
+ GST_STREAM_LOCK (flacdec->sinkpad);
+ g_print ("Got seek lock\n");
+ gst_pad_push_event (flacdec->srcpad, gst_event_new_flush_stop ());
+ GST_DEBUG ("Ready");
flacdec->seek_pending = TRUE;
- else
+ flacdec->seek_value = pos;
+ gst_pad_start_task (flacdec->sinkpad,
+ (GstTaskFunction) gst_flacdec_loop, flacdec->sinkpad);
+ GST_STREAM_UNLOCK (flacdec->sinkpad);
+ } else
res = FALSE;
break;
+ }
default:
res = FALSE;
break;
@@ -754,30 +743,47 @@ gst_flacdec_src_event (GstPad * pad, GstEvent * event)
return res;
}
+static gboolean
+gst_flacdec_sink_activate (GstPad * sinkpad)
+{
+ if (gst_pad_check_pull_range (sinkpad))
+ return gst_pad_activate_pull (sinkpad, TRUE);
+
+ return FALSE;
+}
+
+static gboolean
+gst_flacdec_sink_activate_pull (GstPad * sinkpad, gboolean active)
+{
+ if (active) {
+ /* if we have a scheduler we can start the task */
+ GST_FLACDEC (GST_OBJECT_PARENT (sinkpad))->offset = 0;
+ gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flacdec_loop, sinkpad);
+ } else {
+ gst_pad_stop_task (sinkpad);
+ }
+
+ return TRUE;
+}
+
static GstElementStateReturn
gst_flacdec_change_state (GstElement * element)
{
FlacDec *flacdec = GST_FLACDEC (element);
switch (GST_STATE_TRANSITION (element)) {
- case GST_STATE_NULL_TO_READY:
case GST_STATE_READY_TO_PAUSED:
- flacdec->bs = gst_bytestream_new (flacdec->sinkpad);
flacdec->seek_pending = FALSE;
flacdec->total_samples = 0;
flacdec->eos = FALSE;
+ flacdec->need_discont = TRUE;
if (flacdec->init == FALSE) {
FLAC__seekable_stream_decoder_reset (flacdec->decoder);
}
break;
case GST_STATE_PAUSED_TO_PLAYING:
flacdec->eos = FALSE;
- case GST_STATE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_PAUSED_TO_READY:
- gst_bytestream_destroy (flacdec->bs);
break;
- case GST_STATE_READY_TO_NULL:
default:
break;
}
diff --git a/ext/flac/gstflacdec.h b/ext/flac/gstflacdec.h
index 5b5fd110..04be2e84 100644
--- a/ext/flac/gstflacdec.h
+++ b/ext/flac/gstflacdec.h
@@ -23,7 +23,6 @@
#include <gst/gst.h>
-#include <gst/bytestream/bytestream.h>
#include <FLAC/all.h>
@@ -45,7 +44,7 @@ struct _FlacDec {
GstElement element;
GstPad *sinkpad,*srcpad;
- GstByteStream *bs;
+ guint64 offset;
FLAC__SeekableStreamDecoder *decoder;
gint channels;