summaryrefslogtreecommitdiff
path: root/gst/aiffparse
diff options
context:
space:
mode:
authorMichael Smith <msmith@xiph.org>2008-09-09 01:14:10 +0000
committerMichael Smith <msmith@xiph.org>2008-09-09 01:14:10 +0000
commit8618e452ae28d2df745925cb13961c039d565a48 (patch)
tree54b7526f57335cd7ba3ae2e34abd1f8bbbc420fa /gst/aiffparse
parent5d1c162f060a864db9db4102ea1fddccc83cf553 (diff)
gst/aiffparse/aiffparse.c: Support chunks in AIFF in any order in pull mode, and any order so long as we get COMM bef...
Original commit message from CVS: * 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.
Diffstat (limited to 'gst/aiffparse')
-rw-r--r--gst/aiffparse/aiffparse.c141
1 files changed, 81 insertions, 60 deletions
diff --git a/gst/aiffparse/aiffparse.c b/gst/aiffparse/aiffparse.c
index 09ec2e52e..08f273b7d 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: