summaryrefslogtreecommitdiff
path: root/gst/midi/midiparse.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2013-03-21 09:30:41 +0100
committerWim Taymans <wim.taymans@collabora.co.uk>2013-03-21 09:30:41 +0100
commit76cd0905033613cabb23cfdd6e4344fa5169cdf0 (patch)
tree5565e29b15515b5ae70f8cddb94915552714a682 /gst/midi/midiparse.c
parenta093d65310fc5875dc1b7601688444e9dfe2460d (diff)
downloadgstreamer-plugins-bad-76cd0905033613cabb23cfdd6e4344fa5169cdf0.tar.gz
midiparse: handle midi in RIFF
Diffstat (limited to 'gst/midi/midiparse.c')
-rw-r--r--gst/midi/midiparse.c101
1 files changed, 95 insertions, 6 deletions
diff --git a/gst/midi/midiparse.c b/gst/midi/midiparse.c
index fef99b8d0..cd5cf7083 100644
--- a/gst/midi/midiparse.c
+++ b/gst/midi/midiparse.c
@@ -412,6 +412,85 @@ parse_MTrk (GstMidiParse * midiparse, guint8 * data, guint size)
return TRUE;
}
+static gboolean
+find_midi_chunk (GstMidiParse * midiparse, guint8 * data, guint size,
+ guint * offset, guint * length)
+{
+ guint32 type;
+
+ if (size < 8)
+ goto short_chunk;
+
+ type = GST_STR_FOURCC (data);
+
+ if (type == GST_MAKE_FOURCC ('R', 'I', 'F', 'F')) {
+ guint32 riff_len;
+
+ GST_DEBUG_OBJECT (midiparse, "found RIFF");
+
+ if (size < 12)
+ goto short_chunk;
+
+ if (GST_STR_FOURCC (data + 8) != GST_MAKE_FOURCC ('R', 'M', 'I', 'D'))
+ goto invalid_format;
+
+ riff_len = GST_READ_UINT32_LE (data + 4);
+
+ if (size < riff_len)
+ goto short_chunk;
+
+ data += 12;
+ size -= 12;
+ *offset = 12;
+
+ GST_DEBUG_OBJECT (midiparse, "found RIFF RMID of size %u", riff_len);
+
+ while (TRUE) {
+ guint32 chunk_type;
+ guint32 chunk_len;
+
+ if (riff_len < 8)
+ goto short_chunk;
+
+ chunk_type = GST_STR_FOURCC (data);
+ chunk_len = GST_READ_UINT32_LE (data + 4);
+
+ riff_len -= 8;
+ if (riff_len < chunk_len)
+ goto short_chunk;
+
+ data += 8;
+ size -= 8;
+ *offset += 8;
+ riff_len -= chunk_len;
+
+ if (chunk_type == GST_MAKE_FOURCC ('d', 'a', 't', 'a')) {
+ *length = chunk_len;
+ break;
+ }
+
+ data += chunk_len;
+ size -= chunk_len;
+ }
+ } else {
+ *offset = 0;
+ *length = size;
+ }
+ return TRUE;
+
+ /* ERRORS */
+short_chunk:
+ {
+ GST_LOG_OBJECT (midiparse, "not enough data %u < %u", length + 8, size);
+ return FALSE;
+ }
+invalid_format:
+ {
+ GST_ERROR_OBJECT (midiparse, "invalid format");
+ return FALSE;
+ }
+}
+
static guint
gst_midi_parse_chunk (GstMidiParse * midiparse, guint8 * data, guint size)
{
@@ -443,12 +522,13 @@ gst_midi_parse_chunk (GstMidiParse * midiparse, guint8 * data, guint size)
GST_LOG_OBJECT (midiparse, "ignore chunk");
break;
}
+
return length + 8;
/* ERRORS */
short_chunk:
{
- GST_LOG_OBJECT (midiparse, "not enough data %u < %u", length + 8, size);
+ GST_LOG_OBJECT (midiparse, "not enough data %u < %u", size, length + 8);
return 0;
}
invalid_format:
@@ -463,7 +543,7 @@ gst_midi_parse_parse_song (GstMidiParse * midiparse)
{
GstCaps *outcaps;
guint8 *data;
- guint size;
+ guint size, offset, length;
GST_DEBUG_OBJECT (midiparse, "Parsing song");
@@ -472,15 +552,18 @@ gst_midi_parse_parse_song (GstMidiParse * midiparse)
midiparse->tempo = 60;
- while (size) {
+ if (!find_midi_chunk (midiparse, data, size, &offset, &length))
+ goto invalid_format;
+
+ while (length) {
guint consumed;
- consumed = gst_midi_parse_chunk (midiparse, data, size);
+ consumed = gst_midi_parse_chunk (midiparse, &data[offset], length);
if (consumed == 0)
goto short_file;
- data += consumed;
- size -= consumed;
+ offset += consumed;
+ length -= consumed;
}
outcaps = gst_pad_get_pad_template_caps (midiparse->srcpad);
@@ -503,6 +586,12 @@ short_file:
g_free (data);
return GST_FLOW_ERROR;
}
+invalid_format:
+ {
+ GST_ERROR_OBJECT (midiparse, "invalid format");
+ g_free (data);
+ return GST_FLOW_ERROR;
+ }
}
static GstFlowReturn