static void gst_musepackdec_dispose (GObject * obj);
static gboolean gst_musepackdec_src_event (GstPad * pad, GstEvent * event);
-static const GstFormat *gst_musepackdec_get_formats (GstPad * pad);
-static const GstEventMask *gst_musepackdec_get_event_masks (GstPad * pad);
-static const GstQueryType *gst_musepackdec_get_query_types (GstPad * pad);
-static gboolean gst_musepackdec_src_query (GstPad * pad, GstQueryType type,
- GstFormat * format, gint64 * value);
-static gboolean gst_musepackdec_src_convert (GstPad * pad,
- GstFormat src_format,
- gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
-
-static void gst_musepackdec_loop (GstElement * element);
+static const GstQueryType *gst_musepackdec_get_src_query_types (GstPad * pad);
+static gboolean gst_musepackdec_src_query (GstPad * pad, GstQuery * query);
+
+static gboolean gst_musepackdec_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_musepackdec_sink_activate (GstPad * sinkpad);
+static gboolean
+gst_musepackdec_sink_activate_pull (GstPad * sinkpad, gboolean active);
+
+static void gst_musepackdec_loop (GstPad * sinkpad);
static GstStateChangeReturn
gst_musepackdec_change_state (GstElement * element, GstStateChange transition);
static void
gst_musepackdec_init (GstMusepackDec * musepackdec)
{
- GST_OBJECT_FLAG_SET (musepackdec, GST_ELEMENT_EVENT_AWARE);
+ musepackdec->offset = 0;
musepackdec->r = g_new (mpc_reader, 1);
musepackdec->d = g_new (mpc_decoder, 1);
musepackdec->init = FALSE;
musepackdec->seek_pending = FALSE;
+ musepackdec->flush_pending = FALSE;
+ musepackdec->eos = FALSE;
musepackdec->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get (&sink_template),
"sink");
+ gst_pad_set_event_function (musepackdec->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_musepackdec_sink_event));
gst_element_add_pad (GST_ELEMENT (musepackdec), musepackdec->sinkpad);
+ gst_pad_set_activate_function (musepackdec->sinkpad,
+ gst_musepackdec_sink_activate);
+ gst_pad_set_activatepull_function (musepackdec->sinkpad,
+ gst_musepackdec_sink_activate_pull);
+
musepackdec->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&src_template),
"src");
gst_pad_set_event_function (musepackdec->srcpad,
GST_DEBUG_FUNCPTR (gst_musepackdec_src_event));
- gst_pad_set_event_mask_function (musepackdec->srcpad,
- GST_DEBUG_FUNCPTR (gst_musepackdec_get_event_masks));
+
gst_pad_set_query_function (musepackdec->srcpad,
GST_DEBUG_FUNCPTR (gst_musepackdec_src_query));
gst_pad_set_query_type_function (musepackdec->srcpad,
- GST_DEBUG_FUNCPTR (gst_musepackdec_get_query_types));
- gst_pad_set_convert_function (musepackdec->srcpad,
- GST_DEBUG_FUNCPTR (gst_musepackdec_src_convert));
- gst_pad_set_formats_function (musepackdec->srcpad,
- GST_DEBUG_FUNCPTR (gst_musepackdec_get_formats));
- gst_pad_use_explicit_caps (musepackdec->srcpad);
+ GST_DEBUG_FUNCPTR (gst_musepackdec_get_src_query_types));
+ gst_pad_use_fixed_caps (musepackdec->srcpad);
gst_element_add_pad (GST_ELEMENT (musepackdec), musepackdec->srcpad);
- gst_element_set_loop_function (GST_ELEMENT (musepackdec),
- gst_musepackdec_loop);
+
}
static void
}
static gboolean
+gst_musepackdec_sink_event (GstPad * pad, GstEvent * event)
+{
+ GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad));
+ gboolean res = TRUE;
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_FLUSH_START:
+ musepackdec->flush_pending = TRUE;
+ goto done;
+ break;
+ case GST_EVENT_NEWSEGMENT:
+ musepackdec->flush_pending = TRUE;
+ musepackdec->seek_pending = TRUE;
+ goto done;
+ break;
+ case GST_EVENT_EOS:
+ musepackdec->eos = TRUE;
+ /* fall through */
+ default:
+ res = gst_pad_event_default (pad, event);
+ gst_object_unref (musepackdec);
+ return res;
+ break;
+ }
+
+done:
+ gst_event_unref (event);
+ gst_object_unref (musepackdec);
+ return res;
+
+}
+
+
+static gboolean
gst_musepackdec_src_event (GstPad * pad, GstEvent * event)
{
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:{
+
+ gdouble rate;
+ GstFormat format;
+ GstSeekFlags flags;
+ GstSeekType cur_type;
+ gint64 cur;
+ GstSeekType stop_type;
+ gint64 stop;
+
+ gst_event_parse_seek (event, &rate, &format, &flags,
+ &cur_type, &cur, &stop_type, &stop);
+
+
gint64 offset, len, pos;
GstFormat fmt = GST_FORMAT_TIME;
- /* in time */
- if (!gst_pad_convert (pad,
- (GstFormat) GST_EVENT_SEEK_FORMAT (event),
- GST_EVENT_SEEK_OFFSET (event),
- &fmt, &offset) ||
- !gst_pad_convert (pad,
- GST_FORMAT_DEFAULT, musepackdec->len,
- &fmt, &len) ||
- !gst_pad_convert (pad,
- GST_FORMAT_DEFAULT, musepackdec->pos, &fmt, &pos)) {
+ if (!gst_musepackdec_src_convert (pad, format, cur, &fmt, &offset)) {
+
+ }
+ if (!gst_musepackdec_src_convert (pad, GST_FORMAT_DEFAULT,
+ musepackdec->len, &fmt, &len)) {
+ res = FALSE;
+ break;
+ }
+ if (!gst_musepackdec_src_convert (pad, GST_FORMAT_DEFAULT,
+ musepackdec->pos, &fmt, &pos)) {
res = FALSE;
break;
}
/* offset from start */
- switch (GST_EVENT_SEEK_METHOD (event)) {
- case GST_SEEK_METHOD_SET:
+ switch (cur_type) {
+ case GST_SEEK_TYPE_SET:
break;
- case GST_SEEK_METHOD_CUR:
+ case GST_SEEK_TYPE_CUR:
offset += pos;
break;
- case GST_SEEK_METHOD_END:
+ case GST_SEEK_TYPE_END:
offset = len - offset;
break;
default:
/* store */
musepackdec->seek_pending = TRUE;
- musepackdec->flush_pending =
- GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH;
+ musepackdec->flush_pending = flags & GST_SEEK_FLAG_FLUSH;
musepackdec->seek_time = offset;
res = TRUE;
break;
}
default:
- res = FALSE;
+ res = gst_pad_event_default (pad, event);
+ gst_object_unref (musepackdec);
+ return res;
break;
}
done:
gst_event_unref (event);
-
+ gst_object_unref (musepackdec);
return res;
}
-static const GstFormat *
-gst_musepackdec_get_formats (GstPad * pad)
-{
- static const GstFormat formats[] = {
- GST_FORMAT_BYTES,
- GST_FORMAT_DEFAULT,
- GST_FORMAT_TIME,
- (GstFormat) 0
- };
-
- return formats;
-}
-
-static const GstEventMask *
-gst_musepackdec_get_event_masks (GstPad * pad)
-{
- static const GstEventMask event_masks[] = {
- {GST_EVENT_SEEK,
- (GstEventFlag) (GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH)},
- {(GstEventType) 0, (GstEventFlag) 0}
- };
-
- return event_masks;
-}
-
static const GstQueryType *
-gst_musepackdec_get_query_types (GstPad * pad)
+gst_musepackdec_get_src_query_types (GstPad * pad)
{
static const GstQueryType query_types[] = {
- GST_QUERY_TOTAL,
GST_QUERY_POSITION,
+ GST_QUERY_DURATION,
+ GST_QUERY_CONVERT,
(GstQueryType) 0
};
}
static gboolean
-gst_musepackdec_src_query (GstPad * pad, GstQueryType type,
- GstFormat * format, gint64 * value)
+gst_musepackdec_src_query (GstPad * pad, GstQuery * query)
{
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad));
- gboolean res;
+ GstFormat format = GST_FORMAT_DEFAULT;
+ GstFormat dest_format;
+ gint64 value, dest_value;
+ gboolean res = TRUE;
- if (!musepackdec->init)
- return FALSE;
+ if (!musepackdec->init) {
+ res = FALSE;
+ goto done;
+ }
- switch (type) {
- case GST_QUERY_TOTAL:
- res = gst_pad_convert (pad,
- GST_FORMAT_DEFAULT, musepackdec->len, format, value);
- break;
+ switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:
- res = gst_pad_convert (pad,
- GST_FORMAT_DEFAULT, musepackdec->pos, format, value);
+ gst_query_parse_position (query, &dest_format, NULL);
+ if (!gst_musepackdec_src_convert (pad, format, musepackdec->pos,
+ &dest_format, &dest_value)) {
+ res = FALSE;
+ }
+ gst_query_set_position (query, dest_format, dest_value);
+ break;
+ case GST_QUERY_DURATION:
+ gst_query_parse_duration (query, &dest_format, NULL);
+ if (!gst_musepackdec_src_convert (pad, format, musepackdec->len,
+ &dest_format, &dest_value)) {
+ res = FALSE;
+ break;
+ }
+ gst_query_set_duration (query, dest_format, dest_value);
+ break;
+ case GST_QUERY_CONVERT:
+ gst_query_parse_convert (query, &format, &value, &dest_format,
+ &dest_value);
+ if (!gst_musepackdec_src_convert (pad, format, value, &dest_format,
+ &dest_value)) {
+ res = FALSE;
+ }
+ gst_query_set_convert (query, format, value, dest_format, dest_value);
break;
default:
res = FALSE;
break;
}
+done:
+ g_object_unref (musepackdec);
return res;
}
-static gboolean
+gboolean
gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
{
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad));
gboolean res = TRUE;
- if (!musepackdec->init)
+ if (!musepackdec->init) {
+ gst_object_unref (musepackdec);
return FALSE;
+ }
switch (src_format) {
case GST_FORMAT_DEFAULT:
break;
}
+ gst_object_unref (musepackdec);
return TRUE;
}
GstCaps *caps;
/* set up reading */
- gst_musepack_init_reader (musepackdec->r, musepackdec->bs);
+ gst_musepack_init_reader (musepackdec->r, musepackdec);
/* streaminfo */
mpc_streaminfo_init (&i);
"endianness", G_TYPE_INT, G_BYTE_ORDER,
"channels", G_TYPE_INT, i.channels,
"rate", G_TYPE_INT, i.sample_freq, NULL);
- if (!gst_pad_set_explicit_caps (musepackdec->srcpad, caps)) {
+ gst_pad_use_fixed_caps (musepackdec->srcpad);
+ if (!gst_pad_set_caps (musepackdec->srcpad, caps)) {
GST_ELEMENT_ERROR (musepackdec, CORE, NEGOTIATION, (NULL), (NULL));
return FALSE;
}
return TRUE;
}
+static gboolean
+gst_musepackdec_sink_activate (GstPad * sinkpad)
+{
+
+ if (gst_pad_check_pull_range (sinkpad)) {
+ return gst_pad_activate_pull (sinkpad, TRUE);
+ } else {
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_musepackdec_sink_activate_pull (GstPad * sinkpad, gboolean active)
+{
+
+ gboolean result;
+
+ if (active) {
+
+ result = gst_pad_start_task (sinkpad,
+ (GstTaskFunction) gst_musepackdec_loop, sinkpad);
+ } else {
+ result = gst_pad_stop_task (sinkpad);
+ }
+
+ return result;
+}
+
static void
-gst_musepackdec_loop (GstElement * element)
+gst_musepackdec_loop (GstPad * sinkpad)
{
- GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (element);
+ GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));
GstBuffer *out;
GstFormat fmt;
gint ret;
if (!musepackdec->init) {
if (!gst_musepack_stream_init (musepackdec))
return;
+ gst_pad_push_event (musepackdec->srcpad,
+ gst_event_new_newsegment (FALSE, 1.0,
+ GST_FORMAT_TIME, musepackdec->pos, GST_CLOCK_TIME_NONE, 0));
}
if (musepackdec->seek_pending) {
if (mpc_decoder_seek_seconds (musepackdec->d, seek_time)) {
if (musepackdec->flush_pending) {
musepackdec->flush_pending = FALSE;
- gst_pad_push (musepackdec->srcpad,
- GST_DATA (gst_event_new (GST_EVENT_FLUSH)));
+ gst_pad_push_event (musepackdec->srcpad, gst_event_new_flush_start ());
}
- gst_pad_push (musepackdec->srcpad,
- GST_DATA (gst_event_new_discontinuous (FALSE,
- GST_FORMAT_TIME, musepackdec->seek_time,
- GST_FORMAT_UNDEFINED)));
+ gst_pad_push_event (musepackdec->srcpad,
+ gst_event_new_newsegment (FALSE, 1.0,
+ GST_FORMAT_TIME, musepackdec->seek_time, GST_CLOCK_TIME_NONE, 0));
fmt = GST_FORMAT_DEFAULT;
- gst_pad_convert (musepackdec->srcpad,
+ gst_musepackdec_src_convert (musepackdec->srcpad,
GST_FORMAT_TIME, musepackdec->seek_time,
&fmt, (gint64 *) & musepackdec->pos);
}
out = gst_buffer_new_and_alloc (MPC_DECODER_BUFFER_LENGTH * 4);
ret = mpc_decoder_decode (musepackdec->d,
(MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out), &update_acc, &update_bits);
- if (ret <= 0) {
- if (ret == 0) {
- gst_element_set_eos (element);
- gst_pad_push (musepackdec->srcpad,
- GST_DATA (gst_event_new (GST_EVENT_EOS)));
- } else {
+ if (ret <= 0 || musepackdec->eos) {
+ if (ret < 0) {
GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
+ } else if (!musepackdec->eos) {
+ musepackdec->eos = TRUE;
+ gst_pad_push_event (musepackdec->sinkpad, gst_event_new_eos ());
}
gst_buffer_unref (out);
return;
GST_BUFFER_SIZE (out) = ret * musepackdec->bps;
fmt = GST_FORMAT_TIME;
- gst_pad_query (musepackdec->srcpad,
- GST_QUERY_POSITION, &fmt, (gint64 *) & GST_BUFFER_TIMESTAMP (out));
- gst_pad_convert (musepackdec->srcpad,
- GST_FORMAT_BYTES, GST_BUFFER_SIZE (out),
- &fmt, (gint64 *) & GST_BUFFER_DURATION (out));
+
+ gint64 value;
+
+ gst_musepackdec_src_convert (musepackdec->srcpad,
+ GST_FORMAT_BYTES, GST_BUFFER_SIZE (out), &fmt, &value);
+ GST_BUFFER_DURATION (out) = value;
+
+ gst_musepackdec_src_convert (musepackdec->srcpad,
+ GST_FORMAT_DEFAULT, musepackdec->pos, &fmt, &value);
+ GST_BUFFER_TIMESTAMP (out) = value;
+
musepackdec->pos += GST_BUFFER_SIZE (out) / musepackdec->bps;
- gst_pad_push (musepackdec->srcpad, GST_DATA (out));
+ gst_buffer_set_caps (out, GST_PAD_CAPS (musepackdec->srcpad));
+ gst_pad_push (musepackdec->srcpad, out);
}
static GstStateChangeReturn
gst_musepackdec_change_state (GstElement * element, GstStateChange transition)
{
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (element);
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- musepackdec->bs = gst_bytestream_new (musepackdec->sinkpad);
- break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
musepackdec->seek_pending = FALSE;
musepackdec->init = FALSE;
break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- gst_bytestream_destroy (musepackdec->bs);
- break;
default:
break;
}
- if (GST_ELEMENT_CLASS (parent_class)->change_state)
- return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ return ret;
- return GST_STATE_CHANGE_SUCCESS;
}
static gboolean
plugin_init (GstPlugin * plugin)
{
- return gst_library_load ("gstbytestream") &&
- gst_element_register (plugin, "musepackdec",
+ return gst_element_register (plugin, "musepackdec",
GST_RANK_PRIMARY, GST_TYPE_MUSEPACK_DEC);
}
static mpc_int32_t
gst_musepack_reader_peek (void *this, void *ptr, mpc_int32_t size)
{
- GstByteStream *bs = this;
- guint8 *data;
+ GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
+ GstBuffer *buf = NULL;
gint read;
+ if (musepackdec->eos) {
+ return 0;
+ }
+
do {
- read = gst_bytestream_peek_bytes (bs, &data, size);
+ if (GST_FLOW_OK != gst_pad_pull_range (musepackdec->sinkpad,
+ musepackdec->offset, size, &buf)) {
+ return 0;
+ }
- if (read != size) {
- GstEvent *event;
- guint32 remaining;
+ read = GST_BUFFER_SIZE (buf);
- gst_bytestream_get_status (bs, &remaining, &event);
- if (!event) {
- GST_ELEMENT_ERROR (gst_pad_get_parent (bs->pad),
- RESOURCE, READ, (NULL), (NULL));
- goto done;
- }
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_INTERRUPT:
- gst_event_unref (event);
- goto done;
- case GST_EVENT_EOS:
- gst_event_unref (event);
- goto done;
- case GST_EVENT_FLUSH:
- gst_event_unref (event);
- break;
- case GST_EVENT_DISCONTINUOUS:
- gst_event_unref (event);
- break;
- default:
- gst_pad_event_default (bs->pad, event);
- break;
- }
+ if (musepackdec->eos ||
+ musepackdec->flush_pending || musepackdec->seek_pending) {
+ break;
}
+
+
+ /* FIX ME: do i have to handle those event in sink_event? */
+ /* we pipeline doesnt stop after receive EOS */
+ /*
+
+ if (read != size) {
+ GstEvent *event;
+ guint32 remaining;
+
+ gst_bytestream_get_status (bs, &remaining, &event);
+ if (!event) {
+ GST_ELEMENT_ERROR (gst_pad_get_parent (bs->pad),
+ RESOURCE, READ, (NULL), (NULL));
+ goto done;
+ }
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_INTERRUPT:
+ gst_event_unref (event);
+ goto done;
+ case GST_EVENT_EOS:
+ gst_event_unref (event);
+ goto done;
+ case GST_EVENT_FLUSH:
+ gst_event_unref (event);
+ break;
+ case GST_EVENT_DISCONTINUOUS:
+ gst_event_unref (event);
+ break;
+ default:
+ gst_pad_event_default (bs->pad, event);
+ break;
+ }
+ }
+ */
} while (read != size);
-done:
if (read != 0) {
- memcpy (ptr, data, read);
+ memcpy (ptr, GST_BUFFER_DATA (buf), read);
}
+ gst_buffer_unref (buf);
return read;
}
static mpc_int32_t
gst_musepack_reader_read (void *this, void *ptr, mpc_int32_t size)
{
- GstByteStream *bs = this;
+ GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
gint read;
/* read = peek + flush */
if ((read = gst_musepack_reader_peek (this, ptr, size)) > 0) {
- gst_bytestream_flush_fast (bs, read);
+ musepackdec->offset += read;
}
return read;
}
-static BOOL
+static mpc_bool_t
gst_musepack_reader_seek (void *this, mpc_int32_t offset)
{
- GstByteStream *bs = this;
+ GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
guint8 dummy;
/* hacky hack - if we're after typefind, we'll fail because
gst_musepack_reader_peek (this, &dummy, 1);
/* seek */
- if (!gst_bytestream_seek (bs, offset, GST_SEEK_METHOD_SET))
- return FALSE;
+ musepackdec->offset = offset;
/* get discont */
if (gst_musepack_reader_peek (this, &dummy, 1) != 1)
static mpc_int32_t
gst_musepack_reader_tell (void *this)
{
- GstByteStream *bs = this;
+ GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
+ GstQuery *query;
+ gint64 position;
+ GstFormat format = GST_FORMAT_BYTES;
+
+ query = gst_query_new_position (GST_FORMAT_BYTES);
+ if (gst_pad_query (musepackdec->sinkpad, query)) {
+
+ gst_query_parse_position (query, &format, &position);
+
+ if (format != GST_FORMAT_BYTES) {
+ GstFormat dest_format = GST_FORMAT_BYTES;
+
+ if (!gst_musepackdec_src_convert (musepackdec->srcpad,
+ format, position, &dest_format, &position)) {
+ position = -1;
+ }
- return gst_bytestream_tell (bs);
+ }
+
+ } else {
+ position = -1;
+ }
+ gst_query_unref (query);
+
+ return position;
}
static mpc_int32_t
gst_musepack_reader_get_size (void *this)
{
- GstByteStream *bs = this;
+ GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
+ GstQuery *query;
+ gint64 duration;
+ GstFormat format = GST_FORMAT_BYTES;
+
+ query = gst_query_new_duration (GST_FORMAT_BYTES);
+ if (gst_pad_query (musepackdec->sinkpad, query)) {
+
+ gst_query_parse_duration (query, &format, &duration);
+
+ if (format != GST_FORMAT_BYTES) {
+ GstFormat dest_format = GST_FORMAT_BYTES;
+
+ if (!gst_musepackdec_src_convert (musepackdec->srcpad,
+ format, duration, &dest_format, &duration)) {
+ duration = -1;
+ }
+
+ }
+
+ } else {
+ duration = -1;
+ }
+ gst_query_unref (query);
+
- return gst_bytestream_length (bs);
+ return duration;
}
-static BOOL
+static mpc_bool_t
gst_musepack_reader_canseek (void *this)
{
return TRUE;
}
void
-gst_musepack_init_reader (mpc_reader * r, GstByteStream * bs)
+gst_musepack_init_reader (mpc_reader * r, GstMusepackDec * musepackdec)
{
- r->data = bs;
+ r->data = musepackdec;
r->read = gst_musepack_reader_read;
r->seek = gst_musepack_reader_seek;