mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 13:06:23 +00:00
tagdemux: port to 0.11
This commit is contained in:
parent
3dd31cce39
commit
d3b93e839a
2 changed files with 114 additions and 106 deletions
|
@ -82,21 +82,9 @@ struct _GstTagMuxPrivate
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_tag_mux_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_tag_mux_debug);
|
||||||
#define GST_CAT_DEFAULT gst_tag_mux_debug
|
#define GST_CAT_DEFAULT gst_tag_mux_debug
|
||||||
|
|
||||||
static void
|
#define gst_tag_mux_parent_class parent_class
|
||||||
gst_tag_mux_iface_init (GType tag_type)
|
G_DEFINE_TYPE_WITH_CODE (GstTagMux, gst_tag_mux, GST_TYPE_ELEMENT,
|
||||||
{
|
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
|
||||||
static const GInterfaceInfo tag_setter_info = {
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
g_type_add_interface_static (tag_type, GST_TYPE_TAG_SETTER, &tag_setter_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BOILERPLATE_FULL (GstTagMux, gst_tag_mux,
|
|
||||||
GstElement, GST_TYPE_ELEMENT, gst_tag_mux_iface_init);
|
|
||||||
|
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_tag_mux_change_state (GstElement * element, GstStateChange transition);
|
gst_tag_mux_change_state (GstElement * element, GstStateChange transition);
|
||||||
|
@ -126,13 +114,6 @@ gst_tag_mux_finalize (GObject * obj)
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_tag_mux_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_tag_mux_debug, "tagmux", 0,
|
|
||||||
"tag muxer base class");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_tag_mux_class_init (GstTagMuxClass * klass)
|
gst_tag_mux_class_init (GstTagMuxClass * klass)
|
||||||
{
|
{
|
||||||
|
@ -146,12 +127,15 @@ gst_tag_mux_class_init (GstTagMuxClass * klass)
|
||||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_tag_mux_change_state);
|
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_tag_mux_change_state);
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GstTagMuxPrivate));
|
g_type_class_add_private (klass, sizeof (GstTagMuxPrivate));
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_tag_mux_debug, "tagmux", 0,
|
||||||
|
"tag muxer base class");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_tag_mux_init (GstTagMux * mux, GstTagMuxClass * mux_class)
|
gst_tag_mux_init (GstTagMux * mux)
|
||||||
{
|
{
|
||||||
GstElementClass *element_klass = GST_ELEMENT_CLASS (mux_class);
|
GstElementClass *element_klass = GST_ELEMENT_GET_CLASS (mux);
|
||||||
GstPadTemplate *tmpl;
|
GstPadTemplate *tmpl;
|
||||||
|
|
||||||
mux->priv =
|
mux->priv =
|
||||||
|
@ -163,7 +147,7 @@ gst_tag_mux_init (GstTagMux * mux, GstTagMuxClass * mux_class)
|
||||||
mux->priv->sinkpad = gst_pad_new_from_template (tmpl, "sink");
|
mux->priv->sinkpad = gst_pad_new_from_template (tmpl, "sink");
|
||||||
} else {
|
} else {
|
||||||
g_warning ("GstTagMux subclass '%s' did not install a %s pad template!\n",
|
g_warning ("GstTagMux subclass '%s' did not install a %s pad template!\n",
|
||||||
G_OBJECT_CLASS_NAME (mux_class), "sink");
|
G_OBJECT_CLASS_NAME (element_klass), "sink");
|
||||||
mux->priv->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
mux->priv->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
}
|
}
|
||||||
gst_pad_set_chain_function (mux->priv->sinkpad,
|
gst_pad_set_chain_function (mux->priv->sinkpad,
|
||||||
|
@ -184,7 +168,7 @@ gst_tag_mux_init (GstTagMux * mux, GstTagMuxClass * mux_class)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g_warning ("GstTagMux subclass '%s' did not install a %s pad template!\n",
|
g_warning ("GstTagMux subclass '%s' did not install a %s pad template!\n",
|
||||||
G_OBJECT_CLASS_NAME (mux_class), "source");
|
G_OBJECT_CLASS_NAME (element_klass), "source");
|
||||||
mux->priv->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
mux->priv->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||||
}
|
}
|
||||||
gst_element_add_pad (GST_ELEMENT (mux), mux->priv->srcpad);
|
gst_element_add_pad (GST_ELEMENT (mux), mux->priv->srcpad);
|
||||||
|
@ -226,6 +210,7 @@ gst_tag_mux_render_start_tag (GstTagMux * mux)
|
||||||
GstTagList *taglist;
|
GstTagList *taglist;
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
GstSegment segment;
|
||||||
|
|
||||||
taglist = gst_tag_mux_get_tags (mux);
|
taglist = gst_tag_mux_get_tags (mux);
|
||||||
|
|
||||||
|
@ -243,19 +228,14 @@ gst_tag_mux_render_start_tag (GstTagMux * mux)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GST_BUFFER_CAPS (buffer) == NULL) {
|
mux->priv->start_tag_size = gst_buffer_get_size (buffer);
|
||||||
buffer = gst_buffer_make_metadata_writable (buffer);
|
|
||||||
gst_buffer_set_caps (buffer, GST_PAD_CAPS (mux->priv->srcpad));
|
|
||||||
}
|
|
||||||
|
|
||||||
mux->priv->start_tag_size = GST_BUFFER_SIZE (buffer);
|
|
||||||
GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes",
|
GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes",
|
||||||
mux->priv->start_tag_size);
|
mux->priv->start_tag_size);
|
||||||
|
|
||||||
/* Send newsegment event from byte position 0, so the tag really gets
|
/* Send newsegment event from byte position 0, so the tag really gets
|
||||||
* written to the start of the file, independent of the upstream segment */
|
* written to the start of the file, independent of the upstream segment */
|
||||||
gst_pad_push_event (mux->priv->srcpad,
|
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
|
gst_pad_push_event (mux->priv->srcpad, gst_event_new_segment (&segment));
|
||||||
|
|
||||||
/* Send an event about the new tags to downstream elements */
|
/* Send an event about the new tags to downstream elements */
|
||||||
/* gst_event_new_tag takes ownership of the list, so use a copy */
|
/* gst_event_new_tag takes ownership of the list, so use a copy */
|
||||||
|
@ -286,6 +266,7 @@ gst_tag_mux_render_end_tag (GstTagMux * mux)
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstTagList *taglist;
|
GstTagList *taglist;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
GstSegment segment;
|
||||||
|
|
||||||
taglist = gst_tag_mux_get_tags (mux);
|
taglist = gst_tag_mux_get_tags (mux);
|
||||||
|
|
||||||
|
@ -302,20 +283,15 @@ gst_tag_mux_render_end_tag (GstTagMux * mux)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GST_BUFFER_CAPS (buffer) == NULL) {
|
mux->priv->end_tag_size = gst_buffer_get_size (buffer);
|
||||||
buffer = gst_buffer_make_metadata_writable (buffer);
|
|
||||||
gst_buffer_set_caps (buffer, GST_PAD_CAPS (mux->priv->srcpad));
|
|
||||||
}
|
|
||||||
|
|
||||||
mux->priv->end_tag_size = GST_BUFFER_SIZE (buffer);
|
|
||||||
GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes",
|
GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes",
|
||||||
mux->priv->end_tag_size);
|
mux->priv->end_tag_size);
|
||||||
|
|
||||||
/* Send newsegment event from the end of the file, so it gets written there,
|
/* Send newsegment event from the end of the file, so it gets written there,
|
||||||
independent of whatever new segment events upstream has sent us */
|
independent of whatever new segment events upstream has sent us */
|
||||||
gst_pad_push_event (mux->priv->srcpad,
|
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
|
segment.start = mux->priv->max_offset;
|
||||||
mux->priv->max_offset, -1, 0));
|
gst_pad_push_event (mux->priv->srcpad, gst_event_new_segment (&segment));
|
||||||
|
|
||||||
GST_BUFFER_OFFSET (buffer) = mux->priv->max_offset;
|
GST_BUFFER_OFFSET (buffer) = mux->priv->max_offset;
|
||||||
ret = gst_pad_push (mux->priv->srcpad, buffer);
|
ret = gst_pad_push (mux->priv->srcpad, buffer);
|
||||||
|
@ -334,27 +310,25 @@ static GstEvent *
|
||||||
gst_tag_mux_adjust_event_offsets (GstTagMux * mux,
|
gst_tag_mux_adjust_event_offsets (GstTagMux * mux,
|
||||||
const GstEvent * newsegment_event)
|
const GstEvent * newsegment_event)
|
||||||
{
|
{
|
||||||
GstFormat format;
|
GstSegment segment;
|
||||||
gint64 start, stop, cur;
|
|
||||||
|
|
||||||
gst_event_parse_new_segment ((GstEvent *) newsegment_event, NULL, NULL,
|
gst_event_copy_segment ((GstEvent *) newsegment_event, &segment);
|
||||||
&format, &start, &stop, &cur);
|
|
||||||
|
|
||||||
g_assert (format == GST_FORMAT_BYTES);
|
g_assert (segment.format == GST_FORMAT_BYTES);
|
||||||
|
|
||||||
if (start != -1)
|
if (segment.start != -1)
|
||||||
start += mux->priv->start_tag_size;
|
segment.start += mux->priv->start_tag_size;
|
||||||
if (stop != -1)
|
if (segment.stop != -1)
|
||||||
stop += mux->priv->start_tag_size;
|
segment.stop += mux->priv->start_tag_size;
|
||||||
if (cur != -1)
|
if (segment.time != -1)
|
||||||
cur += mux->priv->start_tag_size;
|
segment.time += mux->priv->start_tag_size;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mux, "adjusting newsegment event offsets to start=%"
|
GST_DEBUG_OBJECT (mux, "adjusting newsegment event offsets to start=%"
|
||||||
G_GINT64_FORMAT ", stop=%" G_GINT64_FORMAT ", cur=%" G_GINT64_FORMAT
|
G_GINT64_FORMAT ", stop=%" G_GINT64_FORMAT ", cur=%" G_GINT64_FORMAT
|
||||||
" (delta = +%" G_GSIZE_FORMAT ")", start, stop, cur,
|
" (delta = +%" G_GSIZE_FORMAT ")", segment.start, segment.stop,
|
||||||
mux->priv->start_tag_size);
|
segment.time, mux->priv->start_tag_size);
|
||||||
|
|
||||||
return gst_event_new_new_segment (TRUE, 1.0, format, start, stop, cur);
|
return gst_event_new_segment (&segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -376,19 +350,18 @@ gst_tag_mux_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
|
||||||
/* Now send the cached newsegment event that we got from upstream */
|
/* Now send the cached newsegment event that we got from upstream */
|
||||||
if (mux->priv->newsegment_ev) {
|
if (mux->priv->newsegment_ev) {
|
||||||
gint64 start;
|
|
||||||
GstEvent *newseg;
|
GstEvent *newseg;
|
||||||
|
GstSegment segment;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mux, "sending cached newsegment event");
|
GST_DEBUG_OBJECT (mux, "sending cached newsegment event");
|
||||||
newseg = gst_tag_mux_adjust_event_offsets (mux, mux->priv->newsegment_ev);
|
newseg = gst_tag_mux_adjust_event_offsets (mux, mux->priv->newsegment_ev);
|
||||||
gst_event_unref (mux->priv->newsegment_ev);
|
gst_event_unref (mux->priv->newsegment_ev);
|
||||||
mux->priv->newsegment_ev = NULL;
|
mux->priv->newsegment_ev = NULL;
|
||||||
|
|
||||||
gst_event_parse_new_segment (newseg, NULL, NULL, NULL, &start, NULL,
|
gst_event_copy_segment (newseg, &segment);
|
||||||
NULL);
|
|
||||||
|
|
||||||
gst_pad_push_event (mux->priv->srcpad, newseg);
|
gst_pad_push_event (mux->priv->srcpad, newseg);
|
||||||
mux->priv->current_offset = start;
|
mux->priv->current_offset = segment.start;
|
||||||
mux->priv->max_offset =
|
mux->priv->max_offset =
|
||||||
MAX (mux->priv->max_offset, mux->priv->current_offset);
|
MAX (mux->priv->max_offset, mux->priv->current_offset);
|
||||||
} else {
|
} else {
|
||||||
|
@ -398,7 +371,7 @@ gst_tag_mux_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
mux->priv->render_start_tag = FALSE;
|
mux->priv->render_start_tag = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = gst_buffer_make_metadata_writable (buffer);
|
buffer = gst_buffer_make_writable (buffer);
|
||||||
|
|
||||||
if (GST_BUFFER_OFFSET (buffer) != GST_BUFFER_OFFSET_NONE) {
|
if (GST_BUFFER_OFFSET (buffer) != GST_BUFFER_OFFSET_NONE) {
|
||||||
GST_LOG_OBJECT (mux, "Adjusting buffer offset from %" G_GINT64_FORMAT
|
GST_LOG_OBJECT (mux, "Adjusting buffer offset from %" G_GINT64_FORMAT
|
||||||
|
@ -407,9 +380,8 @@ gst_tag_mux_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
GST_BUFFER_OFFSET (buffer) += mux->priv->start_tag_size;
|
GST_BUFFER_OFFSET (buffer) += mux->priv->start_tag_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = GST_BUFFER_SIZE (buffer);
|
length = gst_buffer_get_size (buffer);
|
||||||
|
|
||||||
gst_buffer_set_caps (buffer, GST_PAD_CAPS (mux->priv->srcpad));
|
|
||||||
ret = gst_pad_push (mux->priv->srcpad, buffer);
|
ret = gst_pad_push (mux->priv->srcpad, buffer);
|
||||||
|
|
||||||
mux->priv->current_offset += length;
|
mux->priv->current_offset += length;
|
||||||
|
@ -451,15 +423,15 @@ gst_tag_mux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_EVENT_NEWSEGMENT:{
|
case GST_EVENT_SEGMENT:
|
||||||
GstFormat fmt;
|
{
|
||||||
gint64 start;
|
GstSegment segment;
|
||||||
|
|
||||||
gst_event_parse_new_segment (event, NULL, NULL, &fmt, &start, NULL, NULL);
|
gst_event_copy_segment (event, &segment);
|
||||||
|
|
||||||
if (fmt != GST_FORMAT_BYTES) {
|
if (segment.format != GST_FORMAT_BYTES) {
|
||||||
GST_WARNING_OBJECT (mux, "dropping newsegment event in %s format",
|
GST_WARNING_OBJECT (mux, "dropping newsegment event in %s format",
|
||||||
gst_format_get_name (fmt));
|
gst_format_get_name (segment.format));
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -483,7 +455,7 @@ gst_tag_mux_sink_event (GstPad * pad, GstEvent * event)
|
||||||
gst_tag_mux_adjust_event_offsets (mux, event));
|
gst_tag_mux_adjust_event_offsets (mux, event));
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
|
||||||
mux->priv->current_offset = start;
|
mux->priv->current_offset = segment.start;
|
||||||
mux->priv->max_offset =
|
mux->priv->max_offset =
|
||||||
MAX (mux->priv->max_offset, mux->priv->current_offset);
|
MAX (mux->priv->max_offset, mux->priv->current_offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,37 +96,57 @@ guint
|
||||||
gst_tag_get_id3v2_tag_size (GstBuffer * buffer)
|
gst_tag_get_id3v2_tag_size (GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
guint8 *data, flags;
|
guint8 *data, flags;
|
||||||
guint size;
|
gsize size;
|
||||||
|
guint result = 0;
|
||||||
|
|
||||||
g_return_val_if_fail (buffer != NULL, 0);
|
g_return_val_if_fail (buffer != NULL, 0);
|
||||||
|
|
||||||
if (GST_BUFFER_SIZE (buffer) < ID3V2_HDR_SIZE)
|
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
|
||||||
return 0;
|
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (buffer);
|
if (size < ID3V2_HDR_SIZE)
|
||||||
|
goto too_small;
|
||||||
|
|
||||||
/* Check for 'ID3' string at start of buffer */
|
/* Check for 'ID3' string at start of buffer */
|
||||||
if (data[0] != 'I' || data[1] != 'D' || data[2] != '3') {
|
if (data[0] != 'I' || data[1] != 'D' || data[2] != '3')
|
||||||
GST_DEBUG ("No ID3v2 tag in data");
|
goto no_tag;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the flags */
|
/* Read the flags */
|
||||||
flags = data[5];
|
flags = data[5];
|
||||||
|
|
||||||
/* Read the size from the header */
|
/* Read the size from the header */
|
||||||
size = id3v2_read_synch_uint (data + 6, 4);
|
result = id3v2_read_synch_uint (data + 6, 4);
|
||||||
if (size == 0)
|
if (result == 0)
|
||||||
return ID3V2_HDR_SIZE;
|
goto empty;
|
||||||
|
|
||||||
size += ID3V2_HDR_SIZE;
|
result += ID3V2_HDR_SIZE;
|
||||||
|
|
||||||
/* Expand the read size to include a footer if there is one */
|
/* Expand the read size to include a footer if there is one */
|
||||||
if ((flags & ID3V2_HDR_FLAG_FOOTER))
|
if ((flags & ID3V2_HDR_FLAG_FOOTER))
|
||||||
size += 10;
|
result += 10;
|
||||||
|
|
||||||
GST_DEBUG ("ID3v2 tag, size: %u bytes", size);
|
GST_DEBUG ("ID3v2 tag, size: %u bytes", result);
|
||||||
return size;
|
|
||||||
|
done:
|
||||||
|
gst_buffer_unmap (buffer, data, size);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
too_small:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("size too small");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
no_tag:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("No ID3v2 tag in data");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
empty:
|
||||||
|
{
|
||||||
|
GST_DEBUG ("Empty tag size");
|
||||||
|
result = ID3V2_HDR_SIZE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
guint8 *
|
guint8 *
|
||||||
|
@ -174,6 +194,7 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
guint8 *data, *uu_data = NULL;
|
guint8 *data, *uu_data = NULL;
|
||||||
guint read_size;
|
guint read_size;
|
||||||
|
gsize size;
|
||||||
ID3TagsWorking work;
|
ID3TagsWorking work;
|
||||||
guint8 flags;
|
guint8 flags;
|
||||||
guint16 version;
|
guint16 version;
|
||||||
|
@ -184,7 +205,7 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
|
||||||
if (read_size < ID3V2_HDR_SIZE)
|
if (read_size < ID3V2_HDR_SIZE)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (buffer);
|
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
|
||||||
|
|
||||||
/* Read the version */
|
/* Read the version */
|
||||||
version = GST_READ_UINT16_BE (data + 3);
|
version = GST_READ_UINT16_BE (data + 3);
|
||||||
|
@ -193,12 +214,8 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
|
||||||
flags = data[5];
|
flags = data[5];
|
||||||
|
|
||||||
/* Validate the version. At the moment, we only support up to 2.4.0 */
|
/* Validate the version. At the moment, we only support up to 2.4.0 */
|
||||||
if (ID3V2_VER_MAJOR (version) > 4 || ID3V2_VER_MINOR (version) > 0) {
|
if (ID3V2_VER_MAJOR (version) > 4 || ID3V2_VER_MINOR (version) > 0)
|
||||||
GST_WARNING ("ID3v2 tag is from revision 2.%d.%d, "
|
goto wrong_version;
|
||||||
"but decoder only supports 2.%d.%d. Ignoring as per spec.",
|
|
||||||
version >> 8, version & 0xff, ID3V2_VERSION >> 8, ID3V2_VERSION & 0xff);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG ("ID3v2 header flags: %s %s %s %s",
|
GST_DEBUG ("ID3v2 header flags: %s %s %s %s",
|
||||||
(flags & ID3V2_HDR_FLAG_UNSYNC) ? "UNSYNC" : "",
|
(flags & ID3V2_HDR_FLAG_UNSYNC) ? "UNSYNC" : "",
|
||||||
|
@ -207,25 +224,20 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
|
||||||
(flags & ID3V2_HDR_FLAG_FOOTER) ? "FOOTER" : "");
|
(flags & ID3V2_HDR_FLAG_FOOTER) ? "FOOTER" : "");
|
||||||
|
|
||||||
/* This shouldn't really happen! Caller should have checked first */
|
/* This shouldn't really happen! Caller should have checked first */
|
||||||
if (GST_BUFFER_SIZE (buffer) < read_size) {
|
if (size < read_size)
|
||||||
GST_DEBUG
|
goto not_enough_data;
|
||||||
("Found ID3v2 tag with revision 2.%d.%d - need %u more bytes to read",
|
|
||||||
version >> 8, version & 0xff,
|
|
||||||
(guint) (read_size - GST_BUFFER_SIZE (buffer)));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG ("Reading ID3v2 tag with revision 2.%d.%d of size %u", version >> 8,
|
GST_DEBUG ("Reading ID3v2 tag with revision 2.%d.%d of size %u", version >> 8,
|
||||||
version & 0xff, read_size);
|
version & 0xff, read_size);
|
||||||
|
|
||||||
GST_MEMDUMP ("ID3v2 tag", GST_BUFFER_DATA (buffer), read_size);
|
GST_MEMDUMP ("ID3v2 tag", data, read_size);
|
||||||
|
|
||||||
memset (&work, 0, sizeof (ID3TagsWorking));
|
memset (&work, 0, sizeof (ID3TagsWorking));
|
||||||
work.buffer = buffer;
|
work.buffer = buffer;
|
||||||
work.hdr.version = version;
|
work.hdr.version = version;
|
||||||
work.hdr.size = read_size;
|
work.hdr.size = read_size;
|
||||||
work.hdr.flags = flags;
|
work.hdr.flags = flags;
|
||||||
work.hdr.frame_data = GST_BUFFER_DATA (buffer) + ID3V2_HDR_SIZE;
|
work.hdr.frame_data = data + ID3V2_HDR_SIZE;
|
||||||
if (flags & ID3V2_HDR_FLAG_FOOTER)
|
if (flags & ID3V2_HDR_FLAG_FOOTER)
|
||||||
work.hdr.frame_data_size = read_size - ID3V2_HDR_SIZE - 10;
|
work.hdr.frame_data_size = read_size - ID3V2_HDR_SIZE - 10;
|
||||||
else
|
else
|
||||||
|
@ -246,7 +258,27 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
|
||||||
|
|
||||||
g_free (uu_data);
|
g_free (uu_data);
|
||||||
|
|
||||||
|
gst_buffer_unmap (buffer, data, size);
|
||||||
|
|
||||||
return work.tags;
|
return work.tags;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
wrong_version:
|
||||||
|
{
|
||||||
|
GST_WARNING ("ID3v2 tag is from revision 2.%d.%d, "
|
||||||
|
"but decoder only supports 2.%d.%d. Ignoring as per spec.",
|
||||||
|
version >> 8, version & 0xff, ID3V2_VERSION >> 8, ID3V2_VERSION & 0xff);
|
||||||
|
gst_buffer_unmap (buffer, data, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
not_enough_data:
|
||||||
|
{
|
||||||
|
GST_DEBUG
|
||||||
|
("Found ID3v2 tag with revision 2.%d.%d - need %u more bytes to read",
|
||||||
|
version >> 8, version & 0xff, (guint) (read_size - size));
|
||||||
|
gst_buffer_unmap (buffer, data, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint
|
static guint
|
||||||
|
@ -365,9 +397,11 @@ static void
|
||||||
id3v2_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
|
id3v2_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
|
||||||
{
|
{
|
||||||
GstBuffer *blob;
|
GstBuffer *blob;
|
||||||
GstCaps *caps;
|
|
||||||
guint8 *frame_data;
|
guint8 *frame_data;
|
||||||
|
#if 0
|
||||||
|
GstCaps *caps;
|
||||||
gchar *media_type;
|
gchar *media_type;
|
||||||
|
#endif
|
||||||
guint frame_size, header_size;
|
guint frame_size, header_size;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
|
@ -388,7 +422,7 @@ id3v2_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
|
||||||
frame_size = size + header_size;
|
frame_size = size + header_size;
|
||||||
|
|
||||||
blob = gst_buffer_new_and_alloc (frame_size);
|
blob = gst_buffer_new_and_alloc (frame_size);
|
||||||
memcpy (GST_BUFFER_DATA (blob), frame_data, frame_size);
|
gst_buffer_fill (blob, 0, frame_data, frame_size);
|
||||||
|
|
||||||
/* Sanitize frame id */
|
/* Sanitize frame id */
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
|
@ -396,6 +430,7 @@ id3v2_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
|
||||||
frame_data[i] = '_';
|
frame_data[i] = '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
media_type = g_strdup_printf ("application/x-gst-id3v2-%c%c%c%c-frame",
|
media_type = g_strdup_printf ("application/x-gst-id3v2-%c%c%c%c-frame",
|
||||||
g_ascii_tolower (frame_data[0]), g_ascii_tolower (frame_data[1]),
|
g_ascii_tolower (frame_data[0]), g_ascii_tolower (frame_data[1]),
|
||||||
g_ascii_tolower (frame_data[2]), g_ascii_tolower (frame_data[3]));
|
g_ascii_tolower (frame_data[2]), g_ascii_tolower (frame_data[3]));
|
||||||
|
@ -404,6 +439,7 @@ id3v2_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
|
||||||
gst_buffer_set_caps (blob, caps);
|
gst_buffer_set_caps (blob, caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
g_free (media_type);
|
g_free (media_type);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* gst_util_dump_mem (GST_BUFFER_DATA (blob), GST_BUFFER_SIZE (blob)); */
|
/* gst_util_dump_mem (GST_BUFFER_DATA (blob), GST_BUFFER_SIZE (blob)); */
|
||||||
|
|
||||||
|
@ -416,7 +452,6 @@ static gboolean
|
||||||
id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
|
id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
|
||||||
{
|
{
|
||||||
guint frame_hdr_size;
|
guint frame_hdr_size;
|
||||||
guint8 *start;
|
|
||||||
|
|
||||||
/* Extended header if present */
|
/* Extended header if present */
|
||||||
if (work->hdr.flags & ID3V2_HDR_FLAG_EXTHDR) {
|
if (work->hdr.flags & ID3V2_HDR_FLAG_EXTHDR) {
|
||||||
|
@ -438,7 +473,6 @@ id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
|
||||||
work->hdr.frame_data_size -= work->hdr.ext_hdr_size;
|
work->hdr.frame_data_size -= work->hdr.ext_hdr_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
start = GST_BUFFER_DATA (work->buffer);
|
|
||||||
frame_hdr_size = id3v2_frame_hdr_size (work->hdr.version);
|
frame_hdr_size = id3v2_frame_hdr_size (work->hdr.version);
|
||||||
if (work->hdr.frame_data_size <= frame_hdr_size) {
|
if (work->hdr.frame_data_size <= frame_hdr_size) {
|
||||||
GST_DEBUG ("Tag has no data frames. Broken tag");
|
GST_DEBUG ("Tag has no data frames. Broken tag");
|
||||||
|
@ -520,6 +554,7 @@ id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 1
|
#if 1
|
||||||
|
#if 0
|
||||||
GST_LOG
|
GST_LOG
|
||||||
("Frame @ %ld (0x%02lx) id %s size %u, next=%ld (0x%02lx) obsolete=%d",
|
("Frame @ %ld (0x%02lx) id %s size %u, next=%ld (0x%02lx) obsolete=%d",
|
||||||
(glong) (work->hdr.frame_data - start),
|
(glong) (work->hdr.frame_data - start),
|
||||||
|
@ -527,6 +562,7 @@ id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
|
||||||
(glong) (work->hdr.frame_data + frame_hdr_size + frame_size - start),
|
(glong) (work->hdr.frame_data + frame_hdr_size + frame_size - start),
|
||||||
(glong) (work->hdr.frame_data + frame_hdr_size + frame_size - start),
|
(glong) (work->hdr.frame_data + frame_hdr_size + frame_size - start),
|
||||||
obsolete_id);
|
obsolete_id);
|
||||||
|
#endif
|
||||||
#define flag_string(flag,str) \
|
#define flag_string(flag,str) \
|
||||||
((frame_flags & (flag)) ? (str) : "")
|
((frame_flags & (flag)) ? (str) : "")
|
||||||
GST_LOG ("Frame header flags: 0x%04x %s %s %s %s %s %s %s", frame_flags,
|
GST_LOG ("Frame header flags: 0x%04x %s %s %s %s %s %s %s", frame_flags,
|
||||||
|
|
Loading…
Reference in a new issue