diff --git a/ChangeLog b/ChangeLog index 0a3e49b12b..802bbcf5e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-10-27 Michael Smith + + * gst/aiffparse/aiffparse.c: + * gst/aiffparse/aiffparse.h: + Calculate width from depth correctly. + Read SSND header properly (fixes 24 bit AIFF reading). + 2008-10-27 Mark Nauwelaerts * ext/x264/gstx264enc.c: (gst_x264_enc_init_encoder): diff --git a/gst/aiffparse/aiffparse.c b/gst/aiffparse/aiffparse.c index fd269bab67..5738f69746 100644 --- a/gst/aiffparse/aiffparse.c +++ b/gst/aiffparse/aiffparse.c @@ -142,6 +142,7 @@ gst_aiffparse_reset (AIFFParse * aiff) /* These will all be set correctly in the fmt chunk */ aiff->rate = 0; aiff->width = 0; + aiff->depth = 0; aiff->channels = 0; aiff->bps = 0; aiff->offset = 0; @@ -567,6 +568,16 @@ gst_aiffparse_peek_chunk (AIFFParse * aiff, guint32 * tag, guint32 * size) } } +static gboolean +gst_aiffparse_peek_data (AIFFParse * aiff, guint32 size, const guint8 ** data) +{ + if (gst_adapter_available (aiff->adapter) < size) + return FALSE; + + *data = gst_adapter_peek (aiff->adapter, size); + return TRUE; +} + /* * gst_aiffparse_calculate_duration: * @aiff: aiffparse object @@ -658,7 +669,8 @@ gst_aiffparse_parse_comm (AIFFParse * aiff, GstBuffer * buf) aiff->channels = GST_READ_UINT16_BE (data); aiff->total_frames = GST_READ_UINT32_BE (data + 2); - aiff->width = GST_READ_UINT16_BE (data + 6); + aiff->depth = GST_READ_UINT16_BE (data + 6); + aiff->width = GST_ROUND_UP_8 (aiff->depth); aiff->rate = (int) gst_aiffparse_read_IEEE80 (data + 8); if (aiff->is_aifc) { @@ -727,7 +739,7 @@ gst_aiffparse_create_caps (AIFFParse * aiff) caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, aiff->width, - "depth", G_TYPE_INT, aiff->width, + "depth", G_TYPE_INT, aiff->depth, "channels", G_TYPE_INT, aiff->channels, "endianness", G_TYPE_INT, aiff->endianness, "rate", G_TYPE_INT, aiff->rate, @@ -821,16 +833,36 @@ gst_aiffparse_stream_headers (AIFFParse * aiff) } case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{ GstFormat fmt; + GstBuffer *ssndbuf = NULL; + const guint8 *ssnddata = NULL; GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size); - gotdata = TRUE; + + /* Now, read the 8-byte header in the SSND chunk */ if (aiff->streaming) { - gst_adapter_flush (aiff->adapter, 8); + if (!gst_aiffparse_peek_data (aiff, 16, &ssnddata)) + return GST_FLOW_OK; } else { gst_buffer_unref (buf); + if ((res = + gst_pad_pull_range (aiff->sinkpad, aiff->offset, 16, + &ssndbuf)) != GST_FLOW_OK) + goto header_read_error; + ssnddata = GST_BUFFER_DATA (ssndbuf); } - aiff->offset += 8; - aiff->datastart = aiff->offset; + + aiff->ssnd_offset = GST_READ_UINT32_BE (ssnddata + 8); + aiff->ssnd_blocksize = GST_READ_UINT32_BE (ssnddata + 12); + + gotdata = TRUE; + if (aiff->streaming) { + gst_adapter_flush (aiff->adapter, 16); + } else { + gst_buffer_unref (ssndbuf); + } + aiff->offset += 16; + + aiff->datastart = aiff->offset + aiff->ssnd_offset; /* file might be truncated */ fmt = GST_FORMAT_BYTES; if (upstream_size) { diff --git a/gst/aiffparse/aiffparse.h b/gst/aiffparse/aiffparse.h index 5499a9b614..daca59ccf6 100644 --- a/gst/aiffparse/aiffparse.h +++ b/gst/aiffparse/aiffparse.h @@ -76,6 +76,7 @@ struct _AIFFParse { guint32 rate; guint16 channels; guint16 width; + guint16 depth; guint32 endianness; /* real bytes per second used or 0 when no bitrate is known */ @@ -85,6 +86,9 @@ struct _AIFFParse { guint32 total_frames; + guint32 ssnd_offset; + guint32 ssnd_blocksize; + /* position in data part */ guint64 offset; guint64 end_offset;