ext/mad/gstid3tag.c: Works a bit better now, but still needs a rewrite to use get_range instead of this seeking nasti...

Original commit message from CVS:
* ext/mad/gstid3tag.c: (gst_id3_tag_init),
(gst_id3_tag_sink_event), (gst_id3_tag_do_caps_nego),
(gst_id3_tag_chain), (gst_id3_tag_change_state), (plugin_init):
Works a bit better now, but still needs a rewrite to use
get_range instead of this seeking nastiness.
This commit is contained in:
Jan Schmidt 2005-08-22 19:58:58 +00:00
parent 9bd9dbc2f7
commit 152a60bb1c
2 changed files with 97 additions and 50 deletions

View file

@ -1,3 +1,11 @@
2005-08-22 Jan Schmidt <thaytan@mad.scientist.com>
* ext/mad/gstid3tag.c: (gst_id3_tag_init),
(gst_id3_tag_sink_event), (gst_id3_tag_do_caps_nego),
(gst_id3_tag_chain), (gst_id3_tag_change_state), (plugin_init):
Works a bit better now, but still needs a rewrite to use
get_range instead of this seeking nastiness.
2005-08-22 Ronald S. Bultje <rbultje@ronald.bitfreak.net> 2005-08-22 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* configure.ac: * configure.ac:

View file

@ -85,6 +85,7 @@ struct _GstID3Tag
/* state */ /* state */
GstID3TagState state; GstID3TagState state;
GstEvent *segment;
GstBuffer *buffer; GstBuffer *buffer;
gboolean prefer_v1tag; gboolean prefer_v1tag;
glong v1tag_size; glong v1tag_size;
@ -342,6 +343,7 @@ gst_id3_tag_init (GTypeInstance * instance, gpointer g_class)
/* FIXME: for the alli^H^H^H^Hspider - gst_id3_tag_add_src_pad (tag); */ /* FIXME: for the alli^H^H^H^Hspider - gst_id3_tag_add_src_pad (tag); */
tag->parse_mode = GST_ID3_TAG_PARSE_BASE; tag->parse_mode = GST_ID3_TAG_PARSE_BASE;
tag->buffer = NULL; tag->buffer = NULL;
tag->segment = NULL;
} }
static void static void
@ -786,15 +788,16 @@ gst_id3_tag_sink_event (GstPad * pad, GstEvent * event)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT: case GST_EVENT_NEWSEGMENT:
#if 0 GST_DEBUG_OBJECT (tag, "Have new segment event in mode %d", tag->state);
switch (tag->state) { switch (tag->state) {
case GST_ID3_TAG_STATE_READING_V2_TAG:{ case GST_ID3_TAG_STATE_READING_V2_TAG:{
GstFormat format = GST_FORMAT_UNDEFINED;
gint64 value, end_value; gint64 value, end_value;
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value, gst_event_parse_newsegment (event, NULL, &format, &value, &end_value,
&end_value) NULL);
|| gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value,
&end_value)) { if (format == GST_FORMAT_BYTES || format == GST_FORMAT_DEFAULT) {
if (value != if (value !=
(tag->buffer ? GST_BUFFER_OFFSET (tag->buffer) + (tag->buffer ? GST_BUFFER_OFFSET (tag->buffer) +
GST_BUFFER_SIZE (tag->buffer) GST_BUFFER_SIZE (tag->buffer)
@ -805,7 +808,7 @@ gst_id3_tag_sink_event (GstPad * pad, GstEvent * event)
(guint64) (tag->buffer ? GST_BUFFER_OFFSET (tag->buffer) (guint64) (tag->buffer ? GST_BUFFER_OFFSET (tag->buffer)
+ GST_BUFFER_SIZE (tag->buffer) : 0))); + GST_BUFFER_SIZE (tag->buffer) : 0)));
} }
gst_event_unref (event); tag->segment = event;
break; break;
} }
case GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG: case GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG:
@ -821,11 +824,14 @@ gst_id3_tag_sink_event (GstPad * pad, GstEvent * event)
case GST_ID3_TAG_STATE_SEEKING_TO_NORMAL: case GST_ID3_TAG_STATE_SEEKING_TO_NORMAL:
/* just assume it's the right seek for now */ /* just assume it's the right seek for now */
gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL_START); gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL_START);
gst_pad_push_event (tag->srcpad, event); if (tag->segment != NULL)
gst_event_unref (tag->segment);
tag->segment = event;
break; break;
case GST_ID3_TAG_STATE_NORMAL_START: case GST_ID3_TAG_STATE_NORMAL_START:
if (!CAN_BE_DEMUXER (tag)) { if (!CAN_BE_DEMUXER (tag)) {
/* initial discont, ignore */ /* initial discont, ignore */
GST_LOG_OBJECT (tag, "Ignoring initial newsegment");
gst_event_unref (event); gst_event_unref (event);
break; break;
} else { } else {
@ -834,35 +840,36 @@ gst_id3_tag_sink_event (GstPad * pad, GstEvent * event)
/* fall through */ /* fall through */
} }
case GST_ID3_TAG_STATE_NORMAL:{ case GST_ID3_TAG_STATE_NORMAL:{
gint64 value, end_value; GstFormat format = GST_FORMAT_UNDEFINED;
GstEvent *new; gdouble rate;
gint64 value, end_value, base;
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value, gst_event_parse_newsegment (event, &rate, &format, &value, &end_value,
&end_value)) { &base);
if (format == GST_FORMAT_BYTES || format == GST_FORMAT_DEFAULT) {
if (value > tag->v2tag_size) { if (value > tag->v2tag_size) {
value -= tag->v2tag_size; value -= tag->v2tag_size;
} else {
/* FIXME: throw an error here? */
value = 0;
}
new =
gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, value, 0);
gst_event_unref (event); gst_event_unref (event);
gst_pad_push_event (tag->srcpad, new); event =
} else { gst_event_new_newsegment (rate, format, value, end_value,
gst_pad_event_default (pad, event); base);
} }
}
if (tag->srcpad)
gst_pad_push_event (tag->srcpad, event);
else
gst_event_unref (event);
break; break;
} }
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
#endif
break; break;
case GST_EVENT_TAG: case GST_EVENT_TAG:
{ {
GstTagList *list; GstTagList *list;
GST_DEBUG_OBJECT (tag, "Have tags event in mode %d", tag->state);
gst_event_parse_tag (event, &list); gst_event_parse_tag (event, &list);
if (tag->event_tags) { if (tag->event_tags) {
@ -874,6 +881,7 @@ gst_id3_tag_sink_event (GstPad * pad, GstEvent * event)
break; break;
} }
case GST_EVENT_EOS: case GST_EVENT_EOS:
GST_DEBUG_OBJECT (tag, "Have EOS in mode %d", tag->state);
if (tag->v1tag_render && IS_MUXER (tag)) { if (tag->v1tag_render && IS_MUXER (tag)) {
GstTagList *merged; GstTagList *merged;
struct id3_tag *id3; struct id3_tag *id3;
@ -895,6 +903,12 @@ gst_id3_tag_sink_event (GstPad * pad, GstEvent * event)
gst_tag_list_free (merged); gst_tag_list_free (merged);
} }
} }
if (tag->state == GST_ID3_TAG_STATE_SEEKING_TO_NORMAL) {
/* Absorb EOS while finishing reading V1 TAG */
GST_LOG_OBJECT (tag, "Ignoring EOS event after reading id3v1");
gst_event_unref (event);
break;
}
/* fall through */ /* fall through */
default: default:
gst_pad_event_default (pad, event); gst_pad_event_default (pad, event);
@ -977,8 +991,10 @@ gst_id3_tag_do_caps_nego (GstID3Tag * tag, GstBuffer * buffer)
return FALSE; return FALSE;
} }
} }
if (!tag->srcpad) if (tag->srcpad == NULL) {
gst_id3_tag_add_src_pad (tag); gst_id3_tag_add_src_pad (tag);
gst_element_no_more_pads (GST_ELEMENT (tag));
}
if (!gst_pad_is_linked (tag->srcpad)) { if (!gst_pad_is_linked (tag->srcpad)) {
GST_DEBUG_OBJECT (tag, "srcpad not linked, not proceeding"); GST_DEBUG_OBJECT (tag, "srcpad not linked, not proceeding");
tag->parse_mode = GST_ID3_TAG_GET_CLASS (tag)->type; tag->parse_mode = GST_ID3_TAG_GET_CLASS (tag)->type;
@ -1107,19 +1123,18 @@ gst_id3_tag_chain (GstPad * pad, GstBuffer * buffer)
/* seek to beginning */ /* seek to beginning */
GST_LOG_OBJECT (tag, "seeking back to beginning"); GST_LOG_OBJECT (tag, "seeking back to beginning");
gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_SEEKING_TO_NORMAL); gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_SEEKING_TO_NORMAL);
#if 0
if (!gst_pad_push_event (tag->sinkpad, if (!gst_pad_push_event (tag->sinkpad,
gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET | gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH,
GST_SEEK_FLAG_FLUSH, tag->v2tag_size))) { GST_SEEK_TYPE_SET, tag->v2tag_size, GST_SEEK_TYPE_NONE,
0))) {
GST_ELEMENT_ERROR (tag, CORE, SEEK, (NULL), GST_ELEMENT_ERROR (tag, CORE, SEEK, (NULL),
("can't seek back to beginning from reading ID3v1 tag")); ("can't seek back to beginning from reading ID3v1 tag"));
} }
#endif
} else { } else {
gst_id3_tag_send_tag_event (tag); gst_id3_tag_send_tag_event (tag);
/* set eos, we're done parsing tags */ /* set eos, we're done parsing tags */
GST_LOG_OBJECT (tag, "setting EOS after reading ID3v1 tag"); GST_LOG_OBJECT (tag, "Finished reading ID3v1 tag");
gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL); gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL_START);
//gst_element_set_eos (GST_ELEMENT (tag)); //gst_element_set_eos (GST_ELEMENT (tag));
gst_pad_push_event (tag->srcpad, gst_event_new_eos ()); gst_pad_push_event (tag->srcpad, gst_event_new_eos ());
} }
@ -1164,7 +1179,21 @@ gst_id3_tag_chain (GstPad * pad, GstBuffer * buffer)
GST_WARNING_OBJECT (tag, "detected ID3v2 tag, but couldn't parse it"); GST_WARNING_OBJECT (tag, "detected ID3v2 tag, but couldn't parse it");
} }
} }
/* caps nego and typefinding */
/* seek to ID3v1 tag */
gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG);
if (gst_pad_push_event (tag->sinkpad,
gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_END, -128, GST_SEEK_TYPE_NONE, 0))) {
gst_buffer_unref (tag->buffer);
tag->buffer = NULL;
return GST_FLOW_OK;
} else {
GST_DEBUG_OBJECT (tag, "Can't seek to read ID3v1 tag");
}
/* Can't seek, strip off the id3v2 tag and send buffer */
GST_LOG_OBJECT (tag, GST_LOG_OBJECT (tag,
"removing first %ld bytes, because they're the ID3v2 tag", "removing first %ld bytes, because they're the ID3v2 tag",
tag->v2tag_size); tag->v2tag_size);
@ -1180,23 +1209,25 @@ gst_id3_tag_chain (GstPad * pad, GstBuffer * buffer)
GST_BUFFER_OFFSET_END (tag->buffer) + tag->v2tag_size; GST_BUFFER_OFFSET_END (tag->buffer) + tag->v2tag_size;
gst_buffer_unref (tag->buffer); gst_buffer_unref (tag->buffer);
tag->buffer = NULL; tag->buffer = NULL;
if (tag->found_caps == NULL)
if (!gst_id3_tag_do_caps_nego (tag, buffer))
return GST_FLOW_OK;
/* seek to ID3v1 tag */
gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_SEEKING_TO_V1_TAG);
#if 0
if (gst_pad_push_event (tag->sinkpad,
gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_END |
GST_SEEK_FLAG_FLUSH, -128))) {
gst_buffer_unref (buffer);
return GST_FLOW_OK;
}
#endif
gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL_START); gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL_START);
/* fall through */ /* fall through */
case GST_ID3_TAG_STATE_NORMAL_START: case GST_ID3_TAG_STATE_NORMAL_START:
g_assert (tag->buffer == NULL); g_assert (tag->buffer == NULL);
if (!IS_MUXER (tag) && (tag->found_caps == NULL))
if (!gst_id3_tag_do_caps_nego (tag, buffer)) {
gst_buffer_unref (buffer);
return GST_FLOW_OK;
}
/* If we didn't get a segment event to pass on, someone
* downstream is going to complain */
if (tag->segment != NULL) {
gst_pad_push_event (tag->srcpad, tag->segment);
tag->segment = NULL;
}
gst_id3_tag_send_tag_event (tag); gst_id3_tag_send_tag_event (tag);
if (IS_MUXER (tag) && tag->v2tag_render) { if (IS_MUXER (tag) && tag->v2tag_render) {
@ -1224,6 +1255,7 @@ gst_id3_tag_chain (GstPad * pad, GstBuffer * buffer)
gst_tag_list_free (merged); gst_tag_list_free (merged);
} }
} }
gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL); gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL);
tag->v1tag_size_new = (tag->v1tag_render && tag->v1tag_size_new = (tag->v1tag_render &&
IS_MUXER (tag) && IS_MUXER (tag) &&
@ -1274,12 +1306,11 @@ static GstElementStateReturn
gst_id3_tag_change_state (GstElement * element) gst_id3_tag_change_state (GstElement * element)
{ {
GstID3Tag *tag; GstID3Tag *tag;
GstElementStateReturn ret = GST_STATE_SUCCESS;
tag = GST_ID3_TAG (element); tag = GST_ID3_TAG (element);
switch (GST_STATE_TRANSITION (element)) { switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
break;
case GST_STATE_READY_TO_PAUSED: case GST_STATE_READY_TO_PAUSED:
g_assert (tag->parsed_tags == NULL); g_assert (tag->parsed_tags == NULL);
g_assert (tag->buffer == NULL); g_assert (tag->buffer == NULL);
@ -1292,10 +1323,13 @@ gst_id3_tag_change_state (GstElement * element)
gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL_START); gst_id3_tag_set_state (tag, GST_ID3_TAG_STATE_NORMAL_START);
} }
break; break;
case GST_STATE_PAUSED_TO_PLAYING: default:
break;
case GST_STATE_PLAYING_TO_PAUSED:
break; break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_PAUSED_TO_READY: case GST_STATE_PAUSED_TO_READY:
if (tag->parsed_tags) { if (tag->parsed_tags) {
gst_tag_list_free (tag->parsed_tags); gst_tag_list_free (tag->parsed_tags);
@ -1313,13 +1347,18 @@ gst_id3_tag_change_state (GstElement * element)
gst_caps_unref (tag->found_caps); gst_caps_unref (tag->found_caps);
tag->found_caps = NULL; tag->found_caps = NULL;
} }
if (tag->segment) {
gst_event_unref (tag->segment);
tag->segment = NULL;
}
tag->parse_mode = GST_ID3_TAG_PARSE_BASE; tag->parse_mode = GST_ID3_TAG_PARSE_BASE;
break; break;
case GST_STATE_READY_TO_NULL: default:
break; break;
} }
return parent_class->change_state (element);
return ret;
} }
/*** PLUGIN INITIALIZATION ****************************************************/ /*** PLUGIN INITIALIZATION ****************************************************/
@ -1328,7 +1367,7 @@ static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
if (!gst_element_register (plugin, "mad", GST_RANK_PRIMARY, if (!gst_element_register (plugin, "mad", GST_RANK_SECONDARY,
gst_mad_get_type ()) gst_mad_get_type ())
|| !gst_element_register (plugin, "id3demux", GST_RANK_PRIMARY, || !gst_element_register (plugin, "id3demux", GST_RANK_PRIMARY,
gst_id3_tag_get_type (GST_ID3_TAG_PARSE_DEMUX)) gst_id3_tag_get_type (GST_ID3_TAG_PARSE_DEMUX))