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);
}
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)
{
GObjectClass *gobject_class;
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 =
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,
}
} 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);
GstTagList *taglist;
GstEvent *event;
GstFlowReturn ret;
+ GstSegment segment;
taglist = gst_tag_mux_get_tags (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 */
GstBuffer *buffer;
GstTagList *taglist;
GstFlowReturn ret;
+ GstSegment segment;
taglist = gst_tag_mux_get_tags (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);
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
/* 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 {
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
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;
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;
}
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);
}
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 *
{
guint8 *data, *uu_data = NULL;
guint read_size;
+ gsize size;
ID3TagsWorking work;
guint8 flags;
guint16 version;
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);
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" : "",
(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
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
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;
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++) {
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]));
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)); */
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) {
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");
}
}
#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),
(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,