Musepackdec ported to 0.9. There is still a small problem to be solved, after the end of file, the pipeline doens't s...

Original commit message from CVS:
Musepackdec ported to 0.9. There is still a small problem to be solved, after the end of file, the pipeline doens't stop.
This commit is contained in:
Edgard Lima 2005-11-22 15:09:28 +00:00
parent ee0e50b84d
commit a5ef8aef56
8 changed files with 370 additions and 187 deletions

View file

@ -1,3 +1,14 @@
2005-11-22 Edgard Lima <edgard.lima@indt.org.br>
* configure.ac:
* PORTED_09:
* extt/Makefile.am:
* ext/musepack/gstmusepackdec.c:
* ext/musepack/gstmusepackdec.h:
* ext/musepack/gstmusepackreader.c:
* ext/musepack/gstmusepackreader.h:
Musepackdec ported to 0.9. There is still a small problem to be
solved, after the end of file, the pipeline doens't stop.
2005-11-22 Andy Wingo <wingo@pobox.com> 2005-11-22 Andy Wingo <wingo@pobox.com>
* ext/faad/gstfaad.c (gst_faad_event) * ext/faad/gstfaad.c (gst_faad_event)

View file

@ -1,21 +1,22 @@
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. 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): List of ported plugins (update when you commit a ported plugin):
ivorbis (alima) musepack (alima)
gsmdec (alima) ivorbis (alima)
sdl (alima) gsmdec (alima)
speed (fcarvalho) sdl (alima)
gsmenc (fcarvalho) speed (fcarvalho)
faac (fcarvalho) gsmenc (fcarvalho)
wavenc (fcarvalho) faac (fcarvalho)
effectv (wim) wavenc (fcarvalho)
mad (wim) effectv (wim)
mad (wim)
videofilter (wim) videofilter (wim)
aalib (wim) aalib (wim)
libcaca (zeeshan) libcaca (zeeshan)
law (wim) law (wim)
shout2 (zaheer) - not fully tested shout2 (zaheer) - not fully tested
esdsink (arwed) esdsink (arwed)
osssink is partially done in the threaded branch (wim) osssink is partially done in the threaded branch (wim)

View file

@ -399,6 +399,18 @@ else
AC_SUBST(X_LIBS) AC_SUBST(X_LIBS)
fi fi
dnl *** musepack ***
translit(dnm, m, l) AM_CONDITIONAL(USE_MUSEPACK, true)
GST_CHECK_FEATURE(MUSEPACK, [musepackdec], musepack, [
AC_LANG_CPLUSPLUS
AC_CHECK_HEADER([mpcdec/mpcdec.h], [
HAVE_MUSEPACK="yes"
MUSEPACK_LIBS="-lmpcdec"
AC_SUBST(MUSEPACK_LIBS)
], [HAVE_MUSEPACK="no"])
AC_LANG_C
])
dnl *** SDL *** dnl *** SDL ***
translit(dnm, m, l) AM_CONDITIONAL(USE_SDL, true) translit(dnm, m, l) AM_CONDITIONAL(USE_SDL, true)
@ -508,6 +520,7 @@ ext/faac/Makefile
ext/faad/Makefile ext/faad/Makefile
ext/ivorbis/Makefile ext/ivorbis/Makefile
ext/gsm/Makefile ext/gsm/Makefile
ext/musepack/Makefile
ext/sdl/Makefile ext/sdl/Makefile
docs/Makefile docs/Makefile
docs/plugins/Makefile docs/plugins/Makefile

View file

@ -118,11 +118,11 @@ MPEG2ENC_DIR=
MPLEX_DIR= MPLEX_DIR=
# endif # endif
# if USE_MUSEPACK if USE_MUSEPACK
# MUSEPACK_DIR=musepack MUSEPACK_DIR=musepack
# else else
MUSEPACK_DIR= MUSEPACK_DIR=
# endif endif
# if USE_MUSICBRAINZ # if USE_MUSICBRAINZ
# MUSICBRAINZ_DIR=musicbrainz # MUSICBRAINZ_DIR=musicbrainz
@ -228,6 +228,7 @@ DIST_SUBDIRS= \
faac \ faac \
faad \ faad \
gsm \ gsm \
musepack \
sdl \ sdl \
directfb \ directfb \
ivorbis ivorbis

View file

@ -57,16 +57,15 @@ static void gst_musepackdec_init (GstMusepackDec * musepackdec);
static void gst_musepackdec_dispose (GObject * obj); static void gst_musepackdec_dispose (GObject * obj);
static gboolean gst_musepackdec_src_event (GstPad * pad, GstEvent * event); static gboolean gst_musepackdec_src_event (GstPad * pad, GstEvent * event);
static const GstFormat *gst_musepackdec_get_formats (GstPad * pad); static const GstQueryType *gst_musepackdec_get_src_query_types (GstPad * pad);
static const GstEventMask *gst_musepackdec_get_event_masks (GstPad * pad); static gboolean gst_musepackdec_src_query (GstPad * pad, GstQuery * query);
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 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 static GstStateChangeReturn
gst_musepackdec_change_state (GstElement * element, GstStateChange transition); gst_musepackdec_change_state (GstElement * element, GstStateChange transition);
@ -129,38 +128,41 @@ gst_musepackdec_class_init (GstMusepackDecClass * klass)
static void static void
gst_musepackdec_init (GstMusepackDec * musepackdec) 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->r = g_new (mpc_reader, 1);
musepackdec->d = g_new (mpc_decoder, 1); musepackdec->d = g_new (mpc_decoder, 1);
musepackdec->init = FALSE; musepackdec->init = FALSE;
musepackdec->seek_pending = FALSE; musepackdec->seek_pending = FALSE;
musepackdec->flush_pending = FALSE;
musepackdec->eos = FALSE;
musepackdec->sinkpad = musepackdec->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get (&sink_template), gst_pad_new_from_template (gst_static_pad_template_get (&sink_template),
"sink"); "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_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 = musepackdec->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&src_template), gst_pad_new_from_template (gst_static_pad_template_get (&src_template),
"src"); "src");
gst_pad_set_event_function (musepackdec->srcpad, gst_pad_set_event_function (musepackdec->srcpad,
GST_DEBUG_FUNCPTR (gst_musepackdec_src_event)); 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_pad_set_query_function (musepackdec->srcpad,
GST_DEBUG_FUNCPTR (gst_musepackdec_src_query)); GST_DEBUG_FUNCPTR (gst_musepackdec_src_query));
gst_pad_set_query_type_function (musepackdec->srcpad, gst_pad_set_query_type_function (musepackdec->srcpad,
GST_DEBUG_FUNCPTR (gst_musepackdec_get_query_types)); GST_DEBUG_FUNCPTR (gst_musepackdec_get_src_query_types));
gst_pad_set_convert_function (musepackdec->srcpad, gst_pad_use_fixed_caps (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_element_add_pad (GST_ELEMENT (musepackdec), 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 void
@ -176,6 +178,40 @@ gst_musepackdec_dispose (GObject * obj)
G_OBJECT_CLASS (parent_class)->dispose (obj); G_OBJECT_CLASS (parent_class)->dispose (obj);
} }
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 static gboolean
gst_musepackdec_src_event (GstPad * pad, GstEvent * event) gst_musepackdec_src_event (GstPad * pad, GstEvent * event)
{ {
@ -184,31 +220,44 @@ gst_musepackdec_src_event (GstPad * pad, GstEvent * event)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:{ 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; gint64 offset, len, pos;
GstFormat fmt = GST_FORMAT_TIME; GstFormat fmt = GST_FORMAT_TIME;
/* in time */ if (!gst_musepackdec_src_convert (pad, format, cur, &fmt, &offset)) {
if (!gst_pad_convert (pad,
(GstFormat) GST_EVENT_SEEK_FORMAT (event), }
GST_EVENT_SEEK_OFFSET (event), if (!gst_musepackdec_src_convert (pad, GST_FORMAT_DEFAULT,
&fmt, &offset) || musepackdec->len, &fmt, &len)) {
!gst_pad_convert (pad, res = FALSE;
GST_FORMAT_DEFAULT, musepackdec->len, break;
&fmt, &len) || }
!gst_pad_convert (pad, if (!gst_musepackdec_src_convert (pad, GST_FORMAT_DEFAULT,
GST_FORMAT_DEFAULT, musepackdec->pos, &fmt, &pos)) { musepackdec->pos, &fmt, &pos)) {
res = FALSE; res = FALSE;
break; break;
} }
/* offset from start */ /* offset from start */
switch (GST_EVENT_SEEK_METHOD (event)) { switch (cur_type) {
case GST_SEEK_METHOD_SET: case GST_SEEK_TYPE_SET:
break; break;
case GST_SEEK_METHOD_CUR: case GST_SEEK_TYPE_CUR:
offset += pos; offset += pos;
break; break;
case GST_SEEK_METHOD_END: case GST_SEEK_TYPE_END:
offset = len - offset; offset = len - offset;
break; break;
default: default:
@ -224,54 +273,31 @@ gst_musepackdec_src_event (GstPad * pad, GstEvent * event)
/* store */ /* store */
musepackdec->seek_pending = TRUE; musepackdec->seek_pending = TRUE;
musepackdec->flush_pending = musepackdec->flush_pending = flags & GST_SEEK_FLAG_FLUSH;
GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH;
musepackdec->seek_time = offset; musepackdec->seek_time = offset;
res = TRUE; res = TRUE;
break; break;
} }
default: default:
res = FALSE; res = gst_pad_event_default (pad, event);
gst_object_unref (musepackdec);
return res;
break; break;
} }
done: done:
gst_event_unref (event); gst_event_unref (event);
gst_object_unref (musepackdec);
return res; 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 * static const GstQueryType *
gst_musepackdec_get_query_types (GstPad * pad) gst_musepackdec_get_src_query_types (GstPad * pad)
{ {
static const GstQueryType query_types[] = { static const GstQueryType query_types[] = {
GST_QUERY_TOTAL,
GST_QUERY_POSITION, GST_QUERY_POSITION,
GST_QUERY_DURATION,
GST_QUERY_CONVERT,
(GstQueryType) 0 (GstQueryType) 0
}; };
@ -279,41 +305,67 @@ gst_musepackdec_get_query_types (GstPad * pad)
} }
static gboolean static gboolean
gst_musepackdec_src_query (GstPad * pad, GstQueryType type, gst_musepackdec_src_query (GstPad * pad, GstQuery * query)
GstFormat * format, gint64 * value)
{ {
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad)); 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) if (!musepackdec->init) {
return FALSE; res = FALSE;
goto done;
}
switch (type) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_TOTAL:
res = gst_pad_convert (pad,
GST_FORMAT_DEFAULT, musepackdec->len, format, value);
break;
case GST_QUERY_POSITION: case GST_QUERY_POSITION:
res = gst_pad_convert (pad, gst_query_parse_position (query, &dest_format, NULL);
GST_FORMAT_DEFAULT, musepackdec->pos, format, value); 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; break;
default: default:
res = FALSE; res = FALSE;
break; break;
} }
done:
g_object_unref (musepackdec);
return res; return res;
} }
static gboolean gboolean
gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format, gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value) gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
{ {
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad)); GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (gst_pad_get_parent (pad));
gboolean res = TRUE; gboolean res = TRUE;
if (!musepackdec->init) if (!musepackdec->init) {
gst_object_unref (musepackdec);
return FALSE; return FALSE;
}
switch (src_format) { switch (src_format) {
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
@ -365,6 +417,7 @@ gst_musepackdec_src_convert (GstPad * pad, GstFormat src_format,
break; break;
} }
gst_object_unref (musepackdec);
return TRUE; return TRUE;
} }
@ -375,7 +428,7 @@ gst_musepack_stream_init (GstMusepackDec * musepackdec)
GstCaps *caps; GstCaps *caps;
/* set up reading */ /* set up reading */
gst_musepack_init_reader (musepackdec->r, musepackdec->bs); gst_musepack_init_reader (musepackdec->r, musepackdec);
/* streaminfo */ /* streaminfo */
mpc_streaminfo_init (&i); mpc_streaminfo_init (&i);
@ -398,7 +451,8 @@ gst_musepack_stream_init (GstMusepackDec * musepackdec)
"endianness", G_TYPE_INT, G_BYTE_ORDER, "endianness", G_TYPE_INT, G_BYTE_ORDER,
"channels", G_TYPE_INT, i.channels, "channels", G_TYPE_INT, i.channels,
"rate", G_TYPE_INT, i.sample_freq, NULL); "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)); GST_ELEMENT_ERROR (musepackdec, CORE, NEGOTIATION, (NULL), (NULL));
return FALSE; return FALSE;
} }
@ -412,10 +466,38 @@ gst_musepack_stream_init (GstMusepackDec * musepackdec)
return TRUE; return TRUE;
} }
static void static gboolean
gst_musepackdec_loop (GstElement * element) gst_musepackdec_sink_activate (GstPad * sinkpad)
{ {
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (element);
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 (GstPad * sinkpad)
{
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));
GstBuffer *out; GstBuffer *out;
GstFormat fmt; GstFormat fmt;
gint ret; gint ret;
@ -424,6 +506,9 @@ gst_musepackdec_loop (GstElement * element)
if (!musepackdec->init) { if (!musepackdec->init) {
if (!gst_musepack_stream_init (musepackdec)) if (!gst_musepack_stream_init (musepackdec))
return; 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 (musepackdec->seek_pending) {
@ -433,15 +518,13 @@ gst_musepackdec_loop (GstElement * element)
if (mpc_decoder_seek_seconds (musepackdec->d, seek_time)) { if (mpc_decoder_seek_seconds (musepackdec->d, seek_time)) {
if (musepackdec->flush_pending) { if (musepackdec->flush_pending) {
musepackdec->flush_pending = FALSE; musepackdec->flush_pending = FALSE;
gst_pad_push (musepackdec->srcpad, gst_pad_push_event (musepackdec->srcpad, gst_event_new_flush_start ());
GST_DATA (gst_event_new (GST_EVENT_FLUSH)));
} }
gst_pad_push (musepackdec->srcpad, gst_pad_push_event (musepackdec->srcpad,
GST_DATA (gst_event_new_discontinuous (FALSE, gst_event_new_newsegment (FALSE, 1.0,
GST_FORMAT_TIME, musepackdec->seek_time, GST_FORMAT_TIME, musepackdec->seek_time, GST_CLOCK_TIME_NONE, 0));
GST_FORMAT_UNDEFINED)));
fmt = GST_FORMAT_DEFAULT; fmt = GST_FORMAT_DEFAULT;
gst_pad_convert (musepackdec->srcpad, gst_musepackdec_src_convert (musepackdec->srcpad,
GST_FORMAT_TIME, musepackdec->seek_time, GST_FORMAT_TIME, musepackdec->seek_time,
&fmt, (gint64 *) & musepackdec->pos); &fmt, (gint64 *) & musepackdec->pos);
} }
@ -450,13 +533,12 @@ gst_musepackdec_loop (GstElement * element)
out = gst_buffer_new_and_alloc (MPC_DECODER_BUFFER_LENGTH * 4); out = gst_buffer_new_and_alloc (MPC_DECODER_BUFFER_LENGTH * 4);
ret = mpc_decoder_decode (musepackdec->d, ret = mpc_decoder_decode (musepackdec->d,
(MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out), &update_acc, &update_bits); (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out), &update_acc, &update_bits);
if (ret <= 0) { if (ret <= 0 || musepackdec->eos) {
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 {
GST_ERROR_OBJECT (musepackdec, "Failed to decode sample"); 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); gst_buffer_unref (out);
return; return;
@ -464,46 +546,49 @@ gst_musepackdec_loop (GstElement * element)
GST_BUFFER_SIZE (out) = ret * musepackdec->bps; GST_BUFFER_SIZE (out) = ret * musepackdec->bps;
fmt = GST_FORMAT_TIME; fmt = GST_FORMAT_TIME;
gst_pad_query (musepackdec->srcpad,
GST_QUERY_POSITION, &fmt, (gint64 *) & GST_BUFFER_TIMESTAMP (out)); gint64 value;
gst_pad_convert (musepackdec->srcpad,
GST_FORMAT_BYTES, GST_BUFFER_SIZE (out), gst_musepackdec_src_convert (musepackdec->srcpad,
&fmt, (gint64 *) & GST_BUFFER_DURATION (out)); 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; 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 static GstStateChangeReturn
gst_musepackdec_change_state (GstElement * element, GstStateChange transition) gst_musepackdec_change_state (GstElement * element, GstStateChange transition)
{ {
GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (element); 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) { switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
musepackdec->bs = gst_bytestream_new (musepackdec->sinkpad);
break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
musepackdec->seek_pending = FALSE; musepackdec->seek_pending = FALSE;
musepackdec->init = FALSE; musepackdec->init = FALSE;
break; break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_bytestream_destroy (musepackdec->bs);
break;
default: default:
break; break;
} }
if (GST_ELEMENT_CLASS (parent_class)->change_state) return ret;
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
return GST_STATE_CHANGE_SUCCESS;
} }
static gboolean static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
return gst_library_load ("gstbytestream") && return gst_element_register (plugin, "musepackdec",
gst_element_register (plugin, "musepackdec",
GST_RANK_PRIMARY, GST_TYPE_MUSEPACK_DEC); GST_RANK_PRIMARY, GST_TYPE_MUSEPACK_DEC);
} }

View file

@ -21,9 +21,9 @@
#define __GST_MUSEPACK_DEC_H__ #define __GST_MUSEPACK_DEC_H__
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/bytestream/bytestream.h> //#include <gst/bytestream/bytestream.h>
#include <musepack/musepack.h> #include <mpcdec/mpcdec.h>
#include "gstmusepackreader.h" //#include "gstmusepackreader.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -45,7 +45,8 @@ typedef struct _GstMusepackDec {
/* pads */ /* pads */
GstPad *srcpad, *sinkpad; GstPad *srcpad, *sinkpad;
GstByteStream *bs; // GstByteStream *bs;
guint64 offset;
/* MUSEPACK_DEC object */ /* MUSEPACK_DEC object */
mpc_decoder *d; mpc_decoder *d;
@ -59,7 +60,7 @@ typedef struct _GstMusepackDec {
guint64 pos, len; guint64 pos, len;
/* seeks */ /* seeks */
gdouble flush_pending, seek_pending; gdouble flush_pending, seek_pending, eos;
guint64 seek_time; guint64 seek_time;
} GstMusepackDec; } GstMusepackDec;
@ -69,6 +70,10 @@ typedef struct _GstMusepackDecClass {
GType gst_musepackdec_get_type (void); GType gst_musepackdec_get_type (void);
extern gboolean gst_musepackdec_src_convert (GstPad * pad,
GstFormat src_format,
gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
G_END_DECLS G_END_DECLS
#endif /* __GST_MUSEPACK_DEC_H__ */ #endif /* __GST_MUSEPACK_DEC_H__ */

View file

@ -29,48 +29,68 @@
static mpc_int32_t static mpc_int32_t
gst_musepack_reader_peek (void *this, void *ptr, mpc_int32_t size) gst_musepack_reader_peek (void *this, void *ptr, mpc_int32_t size)
{ {
GstByteStream *bs = this; GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
guint8 *data; GstBuffer *buf = NULL;
gint read; gint read;
if (musepackdec->eos) {
return 0;
}
do { do {
read = gst_bytestream_peek_bytes (bs, &data, size); if (GST_FLOW_OK != gst_pad_pull_range (musepackdec->sinkpad,
musepackdec->offset, size, &buf)) {
if (read != size) { return 0;
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;
}
} }
read = GST_BUFFER_SIZE (buf);
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); } while (read != size);
done:
if (read != 0) { if (read != 0) {
memcpy (ptr, data, read); memcpy (ptr, GST_BUFFER_DATA (buf), read);
} }
gst_buffer_unref (buf);
return read; return read;
} }
@ -78,21 +98,21 @@ done:
static mpc_int32_t static mpc_int32_t
gst_musepack_reader_read (void *this, void *ptr, mpc_int32_t size) gst_musepack_reader_read (void *this, void *ptr, mpc_int32_t size)
{ {
GstByteStream *bs = this; GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
gint read; gint read;
/* read = peek + flush */ /* read = peek + flush */
if ((read = gst_musepack_reader_peek (this, ptr, size)) > 0) { if ((read = gst_musepack_reader_peek (this, ptr, size)) > 0) {
gst_bytestream_flush_fast (bs, read); musepackdec->offset += read;
} }
return read; return read;
} }
static BOOL static mpc_bool_t
gst_musepack_reader_seek (void *this, mpc_int32_t offset) gst_musepack_reader_seek (void *this, mpc_int32_t offset)
{ {
GstByteStream *bs = this; GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
guint8 dummy; guint8 dummy;
/* hacky hack - if we're after typefind, we'll fail because /* hacky hack - if we're after typefind, we'll fail because
@ -100,8 +120,7 @@ gst_musepack_reader_seek (void *this, mpc_int32_t offset)
gst_musepack_reader_peek (this, &dummy, 1); gst_musepack_reader_peek (this, &dummy, 1);
/* seek */ /* seek */
if (!gst_bytestream_seek (bs, offset, GST_SEEK_METHOD_SET)) musepackdec->offset = offset;
return FALSE;
/* get discont */ /* get discont */
if (gst_musepack_reader_peek (this, &dummy, 1) != 1) if (gst_musepack_reader_peek (this, &dummy, 1) != 1)
@ -113,29 +132,76 @@ gst_musepack_reader_seek (void *this, mpc_int32_t offset)
static mpc_int32_t static mpc_int32_t
gst_musepack_reader_tell (void *this) gst_musepack_reader_tell (void *this)
{ {
GstByteStream *bs = this; GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (this);
GstQuery *query;
gint64 position;
GstFormat format = GST_FORMAT_BYTES;
return gst_bytestream_tell (bs); 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;
}
}
} else {
position = -1;
}
gst_query_unref (query);
return position;
} }
static mpc_int32_t static mpc_int32_t
gst_musepack_reader_get_size (void *this) 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;
return gst_bytestream_length (bs); 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 duration;
} }
static BOOL static mpc_bool_t
gst_musepack_reader_canseek (void *this) gst_musepack_reader_canseek (void *this)
{ {
return TRUE; return TRUE;
} }
void 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->read = gst_musepack_reader_read;
r->seek = gst_musepack_reader_seek; r->seek = gst_musepack_reader_seek;

View file

@ -20,9 +20,10 @@
#ifndef __GST_MUSEPACK_READER_H__ #ifndef __GST_MUSEPACK_READER_H__
#define __GST_MUSEPACK_READER_H__ #define __GST_MUSEPACK_READER_H__
#include <musepack/musepack.h> #include <mpcdec/mpcdec.h>
#include <gst/bytestream/bytestream.h> //#include <gst/bytestream/bytestream.h>
#include "gstmusepackdec.h"
void gst_musepack_init_reader (mpc_reader * r, GstByteStream * bs); void gst_musepack_init_reader (mpc_reader * r, GstMusepackDec * musepackdec);
#endif /* __GST_MUSEPACK_READER_H__ */ #endif /* __GST_MUSEPACK_READER_H__ */