summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--gst/aiffparse/aiffparse.c141
2 files changed, 88 insertions, 60 deletions
diff --git a/ChangeLog b/ChangeLog
index 46744437..70081033 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-09-08 Michael Smith <msmith@songbirdnest.com>
+
+ * gst/aiffparse/aiffparse.c:
+ Support chunks in AIFF in any order in pull mode, and any order so
+ long as we get COMM before the actual data (SSND) in push mode.
+ Fixes playback of AIFC files.
+
2008-09-08 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/selector/gstinputselector.c: (gst_selector_pad_reset),
diff --git a/gst/aiffparse/aiffparse.c b/gst/aiffparse/aiffparse.c
index 09ec2e52..08f273b7 100644
--- a/gst/aiffparse/aiffparse.c
+++ b/gst/aiffparse/aiffparse.c
@@ -670,9 +670,15 @@ gst_aiffparse_parse_comm (AIFFParse * aiff, GstBuffer * buf)
* either big or little endian */
if (GST_READ_UINT32_LE (data + 18) == GST_MAKE_FOURCC ('N', 'O', 'N', 'E'))
aiff->endianness = G_BIG_ENDIAN;
- else if (GST_READ_UINT32_LE (data + 18) == GST_MAKE_FOURCC ('s', 'o', 'w',
- 't'))
+ else if (GST_READ_UINT32_LE (data + 18) ==
+ GST_MAKE_FOURCC ('s', 'o', 'w', 't'))
aiff->endianness = G_LITTLE_ENDIAN;
+ else {
+ GST_WARNING_OBJECT (aiff, "Unsupported compression in AIFC "
+ "file: %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (GST_READ_UINT32_LE (data + 18)));
+ return FALSE;
+ }
} else
aiff->endianness = G_BIG_ENDIAN;
@@ -742,68 +748,17 @@ gst_aiffparse_stream_headers (AIFFParse * aiff)
GstBuffer *buf;
guint32 tag, size;
gboolean gotdata = FALSE;
+ gboolean done = FALSE;
GstEvent **event_p;
GstFormat bformat;
gint64 upstream_size = 0;
- /* search for "comm" chunk, which should be first */
- while (!aiff->got_comm) {
- /* The header starts with a 'comm' tag */
- if (aiff->streaming) {
- if (!gst_aiffparse_peek_chunk (aiff, &tag, &size))
- return GST_FLOW_OK;
-
- gst_adapter_flush (aiff->adapter, 8);
- aiff->offset += 8;
-
- buf = gst_adapter_take_buffer (aiff->adapter, size);
- } else {
- if ((res = gst_aiffparse_read_chunk (aiff,
- &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
- return res;
- }
-
- /* TODO: allow some non-COMM chunks here */
-
- if (tag != GST_MAKE_FOURCC ('C', 'O', 'M', 'M')) {
- gst_buffer_unref (buf);
- goto invalid_aiff;
- }
-
- if (!gst_aiffparse_parse_comm (aiff, buf)) {
- gst_buffer_unref (buf);
- goto parse_header_error;
- }
-
- /* do sanity checks of header fields */
- if (aiff->channels == 0)
- goto no_channels;
- if (aiff->rate == 0)
- goto no_rate;
-
- GST_DEBUG_OBJECT (aiff, "creating the caps");
-
- aiff->caps = gst_aiffparse_create_caps (aiff);
- if (!aiff->caps)
- goto unknown_format;
-
- gst_pad_set_caps (aiff->srcpad, aiff->caps);
-
- aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
- aiff->bps = aiff->bytes_per_sample * aiff->rate;
-
- if (aiff->bytes_per_sample <= 0)
- goto no_bytes_per_sample;
-
- aiff->got_comm = TRUE;
- }
-
bformat = GST_FORMAT_BYTES;
gst_pad_query_peer_duration (aiff->sinkpad, &bformat, &upstream_size);
GST_DEBUG_OBJECT (aiff, "upstream size %" G_GUINT64_FORMAT, upstream_size);
/* loop headers until we get data */
- while (!gotdata) {
+ while (!done) {
if (aiff->streaming) {
if (!gst_aiffparse_peek_chunk_info (aiff, &tag, &size))
return GST_FLOW_OK;
@@ -823,13 +778,58 @@ gst_aiffparse_stream_headers (AIFFParse * aiff)
/* We just keep reading chunks until we find the one we're interested in.
*/
switch (tag) {
+ case GST_MAKE_FOURCC ('C', 'O', 'M', 'M'):{
+ if (aiff->streaming) {
+ if (!gst_aiffparse_peek_chunk (aiff, &tag, &size))
+ return GST_FLOW_OK;
+
+ gst_adapter_flush (aiff->adapter, 8);
+ aiff->offset += 8;
+
+ buf = gst_adapter_take_buffer (aiff->adapter, size);
+ } else {
+ if ((res = gst_aiffparse_read_chunk (aiff,
+ &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
+ return res;
+ }
+
+ if (!gst_aiffparse_parse_comm (aiff, buf)) {
+ gst_buffer_unref (buf);
+ goto parse_header_error;
+ }
+
+ gst_buffer_unref (buf);
+
+ /* do sanity checks of header fields */
+ if (aiff->channels == 0)
+ goto no_channels;
+ if (aiff->rate == 0)
+ goto no_rate;
+
+ GST_DEBUG_OBJECT (aiff, "creating the caps");
+
+ aiff->caps = gst_aiffparse_create_caps (aiff);
+ if (!aiff->caps)
+ goto unknown_format;
+
+ gst_pad_set_caps (aiff->srcpad, aiff->caps);
+
+ aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
+ aiff->bps = aiff->bytes_per_sample * aiff->rate;
+
+ if (aiff->bytes_per_sample <= 0)
+ goto no_bytes_per_sample;
+
+ aiff->got_comm = TRUE;
+ break;
+ }
case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{
GstFormat fmt;
GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size);
+ gotdata = TRUE;
if (aiff->streaming) {
gst_adapter_flush (aiff->adapter, 8);
- gotdata = TRUE;
} else {
gst_buffer_unref (buf);
}
@@ -849,6 +849,9 @@ gst_aiffparse_stream_headers (AIFFParse * aiff)
aiff->offset += size;
}
GST_DEBUG_OBJECT (aiff, "datasize = %d", size);
+ if (aiff->streaming) {
+ done = TRUE;
+ }
break;
}
default:
@@ -857,10 +860,23 @@ gst_aiffparse_stream_headers (AIFFParse * aiff)
if (upstream_size && (aiff->offset >= upstream_size)) {
/* Now we have gone through the whole file */
- gotdata = TRUE;
+ done = TRUE;
}
}
+ /* We read all the chunks (in pull mode) or reached the SSND chunk
+ * (in push mode). We must have both COMM and SSND now; error out
+ * otherwise.
+ */
+ if (!aiff->got_comm) {
+ GST_WARNING_OBJECT (aiff, "Failed to find COMM chunk");
+ goto no_header;
+ }
+ if (!gotdata) {
+ GST_WARNING_OBJECT (aiff, "Failed to find SSND chunk");
+ goto no_data;
+ }
+
GST_DEBUG_OBJECT (aiff, "Finished parsing headers");
if (gst_aiffparse_calculate_duration (aiff)) {
@@ -888,11 +904,16 @@ gst_aiffparse_stream_headers (AIFFParse * aiff)
return GST_FLOW_OK;
/* ERROR */
-invalid_aiff:
+no_header:
+ {
+ GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
+ ("Invalid AIFF header (no COMM found)"));
+ return GST_FLOW_ERROR;
+ }
+no_data:
{
GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
- ("Invalid AIFF header (no COMM at start): %"
- GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
+ ("Invalid AIFF: no SSND found"));
return GST_FLOW_ERROR;
}
parse_header_error: