tagdemux: port to 0.11

This commit is contained in:
Wim Taymans 2011-08-17 10:57:52 +02:00
parent 3dd31cce39
commit d3b93e839a
2 changed files with 114 additions and 106 deletions

View file

@ -82,21 +82,9 @@ struct _GstTagMuxPrivate
GST_DEBUG_CATEGORY_STATIC (gst_tag_mux_debug);
#define GST_CAT_DEFAULT gst_tag_mux_debug
static void
gst_tag_mux_iface_init (GType tag_type)
{
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);
#define gst_tag_mux_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstTagMux, gst_tag_mux, GST_TYPE_ELEMENT,
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
static GstStateChangeReturn
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);
}
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
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);
g_type_class_add_private (klass, sizeof (GstTagMuxPrivate));
GST_DEBUG_CATEGORY_INIT (gst_tag_mux_debug, "tagmux", 0,
"tag muxer base class");
}
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;
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");
} else {
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);
}
gst_pad_set_chain_function (mux->priv->sinkpad,
@ -184,7 +168,7 @@ gst_tag_mux_init (GstTagMux * mux, GstTagMuxClass * mux_class)
}
} else {
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);
}
gst_element_add_pad (GST_ELEMENT (mux), mux->priv->srcpad);
@ -226,6 +210,7 @@ gst_tag_mux_render_start_tag (GstTagMux * mux)
GstTagList *taglist;
GstEvent *event;
GstFlowReturn ret;
GstSegment segment;
taglist = gst_tag_mux_get_tags (mux);
@ -243,19 +228,14 @@ gst_tag_mux_render_start_tag (GstTagMux * mux)
return GST_FLOW_OK;
}
if (GST_BUFFER_CAPS (buffer) == NULL) {
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);
mux->priv->start_tag_size = gst_buffer_get_size (buffer);
GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes",
mux->priv->start_tag_size);
/* Send newsegment event from byte position 0, so the tag really gets
* written to the start of the file, independent of the upstream segment */
gst_pad_push_event (mux->priv->srcpad,
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
gst_segment_init (&segment, GST_FORMAT_BYTES);
gst_pad_push_event (mux->priv->srcpad, gst_event_new_segment (&segment));
/* Send an event about the new tags to downstream elements */
/* 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;
GstTagList *taglist;
GstFlowReturn ret;
GstSegment segment;
taglist = gst_tag_mux_get_tags (mux);
@ -302,20 +283,15 @@ gst_tag_mux_render_end_tag (GstTagMux * mux)
return GST_FLOW_OK;
}
if (GST_BUFFER_CAPS (buffer) == NULL) {
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);
mux->priv->end_tag_size = gst_buffer_get_size (buffer);
GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes",
mux->priv->end_tag_size);
/* Send newsegment event from the end of the file, so it gets written there,
independent of whatever new segment events upstream has sent us */
gst_pad_push_event (mux->priv->srcpad,
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
mux->priv->max_offset, -1, 0));
gst_segment_init (&segment, GST_FORMAT_BYTES);
segment.start = mux->priv->max_offset;
gst_pad_push_event (mux->priv->srcpad, gst_event_new_segment (&segment));
GST_BUFFER_OFFSET (buffer) = mux->priv->max_offset;
ret = gst_pad_push (mux->priv->srcpad, buffer);
@ -334,27 +310,25 @@ static GstEvent *
gst_tag_mux_adjust_event_offsets (GstTagMux * mux,
const GstEvent * newsegment_event)
{
GstFormat format;
gint64 start, stop, cur;
GstSegment segment;
gst_event_parse_new_segment ((GstEvent *) newsegment_event, NULL, NULL,
&format, &start, &stop, &cur);
gst_event_copy_segment ((GstEvent *) newsegment_event, &segment);
g_assert (format == GST_FORMAT_BYTES);
g_assert (segment.format == GST_FORMAT_BYTES);
if (start != -1)
start += mux->priv->start_tag_size;
if (stop != -1)
stop += mux->priv->start_tag_size;
if (cur != -1)
cur += mux->priv->start_tag_size;
if (segment.start != -1)
segment.start += mux->priv->start_tag_size;
if (segment.stop != -1)
segment.stop += mux->priv->start_tag_size;
if (segment.time != -1)
segment.time += mux->priv->start_tag_size;
GST_DEBUG_OBJECT (mux, "adjusting newsegment event offsets to start=%"
G_GINT64_FORMAT ", stop=%" G_GINT64_FORMAT ", cur=%" G_GINT64_FORMAT
" (delta = +%" G_GSIZE_FORMAT ")", start, stop, cur,
mux->priv->start_tag_size);
" (delta = +%" G_GSIZE_FORMAT ")", segment.start, segment.stop,
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
@ -376,19 +350,18 @@ gst_tag_mux_chain (GstPad * pad, GstBuffer * buffer)
/* Now send the cached newsegment event that we got from upstream */
if (mux->priv->newsegment_ev) {
gint64 start;
GstEvent *newseg;
GstSegment segment;
GST_DEBUG_OBJECT (mux, "sending cached newsegment event");
newseg = gst_tag_mux_adjust_event_offsets (mux, mux->priv->newsegment_ev);
gst_event_unref (mux->priv->newsegment_ev);
mux->priv->newsegment_ev = NULL;
gst_event_parse_new_segment (newseg, NULL, NULL, NULL, &start, NULL,
NULL);
gst_event_copy_segment (newseg, &segment);
gst_pad_push_event (mux->priv->srcpad, newseg);
mux->priv->current_offset = start;
mux->priv->current_offset = segment.start;
mux->priv->max_offset =
MAX (mux->priv->max_offset, mux->priv->current_offset);
} else {
@ -398,7 +371,7 @@ gst_tag_mux_chain (GstPad * pad, GstBuffer * buffer)
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) {
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;
}
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);
mux->priv->current_offset += length;
@ -451,15 +423,15 @@ gst_tag_mux_sink_event (GstPad * pad, GstEvent * event)
result = TRUE;
break;
}
case GST_EVENT_NEWSEGMENT:{
GstFormat fmt;
gint64 start;
case GST_EVENT_SEGMENT:
{
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_format_get_name (fmt));
gst_format_get_name (segment.format));
gst_event_unref (event);
break;
}
@ -483,7 +455,7 @@ gst_tag_mux_sink_event (GstPad * pad, GstEvent * event)
gst_tag_mux_adjust_event_offsets (mux, event));
gst_event_unref (event);
mux->priv->current_offset = start;
mux->priv->current_offset = segment.start;
mux->priv->max_offset =
MAX (mux->priv->max_offset, mux->priv->current_offset);
}

View file

@ -96,37 +96,57 @@ guint
gst_tag_get_id3v2_tag_size (GstBuffer * buffer)
{
guint8 *data, flags;
guint size;
gsize size;
guint result = 0;
g_return_val_if_fail (buffer != NULL, 0);
if (GST_BUFFER_SIZE (buffer) < ID3V2_HDR_SIZE)
return 0;
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
data = GST_BUFFER_DATA (buffer);
if (size < ID3V2_HDR_SIZE)
goto too_small;
/* Check for 'ID3' string at start of buffer */
if (data[0] != 'I' || data[1] != 'D' || data[2] != '3') {
GST_DEBUG ("No ID3v2 tag in data");
return 0;
}
if (data[0] != 'I' || data[1] != 'D' || data[2] != '3')
goto no_tag;
/* Read the flags */
flags = data[5];
/* Read the size from the header */
size = id3v2_read_synch_uint (data + 6, 4);
if (size == 0)
return ID3V2_HDR_SIZE;
result = id3v2_read_synch_uint (data + 6, 4);
if (result == 0)
goto empty;
size += ID3V2_HDR_SIZE;
result += ID3V2_HDR_SIZE;
/* Expand the read size to include a footer if there is one */
if ((flags & ID3V2_HDR_FLAG_FOOTER))
size += 10;
result += 10;
GST_DEBUG ("ID3v2 tag, size: %u bytes", size);
return size;
GST_DEBUG ("ID3v2 tag, size: %u bytes", result);
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 *
@ -174,6 +194,7 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
{
guint8 *data, *uu_data = NULL;
guint read_size;
gsize size;
ID3TagsWorking work;
guint8 flags;
guint16 version;
@ -184,7 +205,7 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
if (read_size < ID3V2_HDR_SIZE)
return NULL;
data = GST_BUFFER_DATA (buffer);
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
/* Read the version */
version = GST_READ_UINT16_BE (data + 3);
@ -193,12 +214,8 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
flags = data[5];
/* 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) {
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);
return NULL;
}
if (ID3V2_VER_MAJOR (version) > 4 || ID3V2_VER_MINOR (version) > 0)
goto wrong_version;
GST_DEBUG ("ID3v2 header flags: %s %s %s %s",
(flags & ID3V2_HDR_FLAG_UNSYNC) ? "UNSYNC" : "",
@ -207,25 +224,20 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
(flags & ID3V2_HDR_FLAG_FOOTER) ? "FOOTER" : "");
/* This shouldn't really happen! Caller should have checked first */
if (GST_BUFFER_SIZE (buffer) < read_size) {
GST_DEBUG
("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;
}
if (size < read_size)
goto not_enough_data;
GST_DEBUG ("Reading ID3v2 tag with revision 2.%d.%d of size %u", version >> 8,
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));
work.buffer = buffer;
work.hdr.version = version;
work.hdr.size = read_size;
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)
work.hdr.frame_data_size = read_size - ID3V2_HDR_SIZE - 10;
else
@ -246,7 +258,27 @@ gst_tag_list_from_id3v2_tag (GstBuffer * buffer)
g_free (uu_data);
gst_buffer_unmap (buffer, data, size);
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
@ -365,9 +397,11 @@ static void
id3v2_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
{
GstBuffer *blob;
GstCaps *caps;
guint8 *frame_data;
#if 0
GstCaps *caps;
gchar *media_type;
#endif
guint frame_size, header_size;
guint i;
@ -388,7 +422,7 @@ id3v2_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
frame_size = size + header_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 */
for (i = 0; i < 4; i++) {
@ -396,6 +430,7 @@ id3v2_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
frame_data[i] = '_';
}
#if 0
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[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_caps_unref (caps);
g_free (media_type);
#endif
/* 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)
{
guint frame_hdr_size;
guint8 *start;
/* Extended header if present */
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;
}
start = GST_BUFFER_DATA (work->buffer);
frame_hdr_size = id3v2_frame_hdr_size (work->hdr.version);
if (work->hdr.frame_data_size <= frame_hdr_size) {
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 0
GST_LOG
("Frame @ %ld (0x%02lx) id %s size %u, next=%ld (0x%02lx) obsolete=%d",
(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),
obsolete_id);
#endif
#define flag_string(flag,str) \
((frame_flags & (flag)) ? (str) : "")
GST_LOG ("Frame header flags: 0x%04x %s %s %s %s %s %s %s", frame_flags,