summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.net>2006-09-04 15:06:25 +0000
committerTim-Philipp Müller <tim@centricular.net>2006-09-04 15:06:25 +0000
commita0fa3b2917891bc36e3c186bc2d5389233571331 (patch)
tree544e7c0721608fbfa182ce0fa47eaf2c58f815ac
parentfc559fff48fc72e04aca551519d5bf8dfef8d877 (diff)
gst/matroska/: not perfect yet though, needs some tweaking in flacdec; also, seeking could be better.
Original commit message from CVS: * gst/matroska/matroska-demux.c: (gst_matroska_demux_push_hdr_buf), (gst_matroska_demux_push_flac_codec_priv_data), (gst_matroska_demux_push_xiph_codec_priv_data), (gst_matroska_demux_parse_blockgroup_or_simpleblock), (gst_matroska_demux_video_caps), (gst_matroska_demux_audio_caps): * gst/matroska/matroska-ids.h: Add basic FLAC support (#311586), not perfect yet though, needs some tweaking in flacdec; also, seeking could be better. Do better bounds checking when deserialising vorbis stream headers to make sure we don't read beyond the end of the buffer on bad input.
-rw-r--r--ChangeLog13
-rw-r--r--gst/matroska/matroska-demux.c118
-rw-r--r--gst/matroska/matroska-ids.h6
3 files changed, 115 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index debc6818..4780d757 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2006-09-04 Tim-Philipp Müller <tim at centricular dot net>
+
+ * gst/matroska/matroska-demux.c: (gst_matroska_demux_push_hdr_buf),
+ (gst_matroska_demux_push_flac_codec_priv_data),
+ (gst_matroska_demux_push_xiph_codec_priv_data),
+ (gst_matroska_demux_parse_blockgroup_or_simpleblock),
+ (gst_matroska_demux_video_caps), (gst_matroska_demux_audio_caps):
+ * gst/matroska/matroska-ids.h:
+ Add basic FLAC support (#311586), not perfect yet though, needs some
+ tweaking in flacdec; also, seeking could be better.
+ Do better bounds checking when deserialising vorbis stream headers
+ to make sure we don't read beyond the end of the buffer on bad input.
+
2006-09-04 Wim Taymans <wim@fluendo.com>
Patch by: Alessandro Decina <alessandro at nnva dot org>
diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c
index 91556638..3d6208de 100644
--- a/gst/matroska/matroska-demux.c
+++ b/gst/matroska/matroska-demux.c
@@ -2041,40 +2041,102 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux)
}
static gboolean
+gst_matroska_demux_push_hdr_buf (GstMatroskaDemux * demux,
+ GstMatroskaTrackContext * stream, guint8 * data, guint len)
+{
+ GstFlowReturn flow;
+ GstBuffer *header_buf = NULL;
+
+ flow = gst_pad_alloc_buffer_and_set_caps (stream->pad,
+ GST_BUFFER_OFFSET_NONE, len, stream->caps, &header_buf);
+
+ if (flow == GST_FLOW_OK) {
+ memcpy (GST_BUFFER_DATA (header_buf), data, len);
+ flow = gst_pad_push (stream->pad, header_buf);
+ }
+
+ if (flow != GST_FLOW_OK && flow != GST_FLOW_NOT_LINKED)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_matroska_demux_push_flac_codec_priv_data (GstMatroskaDemux * demux,
+ GstMatroskaTrackContext * stream)
+{
+ guint8 *pdata;
+ guint off, len;
+
+ GST_LOG_OBJECT (demux, "priv data size = %u", stream->codec_priv_size);
+
+ pdata = (guint8 *) stream->codec_priv;
+
+ /* need at least 'fLaC' marker + STREAMINFO metadata block */
+ if (stream->codec_priv_size < ((4) + (4 + 34))) {
+ GST_WARNING_OBJECT (demux, "not enough codec priv data for flac headers");
+ return FALSE;
+ }
+
+ if (memcmp (pdata, "fLaC", 4) != 0) {
+ GST_WARNING_OBJECT (demux, "no flac marker at start of stream headers");
+ return FALSE;
+ }
+
+ if (!gst_matroska_demux_push_hdr_buf (demux, stream, pdata, 4))
+ return FALSE;
+
+ off = 4; /* skip fLaC marker */
+ while (off < stream->codec_priv_size) {
+ len = GST_READ_UINT8 (pdata + off + 1) << 16;
+ len |= GST_READ_UINT8 (pdata + off + 2) << 8;
+ len |= GST_READ_UINT8 (pdata + off + 3);
+
+ GST_DEBUG_OBJECT (demux, "header packet: len=%u bytes, flags=0x%02x",
+ len, (guint) pdata[off]);
+
+ if (!gst_matroska_demux_push_hdr_buf (demux, stream, pdata + off, len))
+ return FALSE;
+
+ off += 4 + len;
+ }
+
+ return TRUE;
+}
+
+static gboolean
gst_matroska_demux_push_xiph_codec_priv_data (GstMatroskaDemux * demux,
GstMatroskaTrackContext * stream)
{
- GstFlowReturn ret;
- GstBuffer *priv;
- guint32 offset, length;
- guchar *p;
- gint i;
+ guint8 *p = (guint8 *) stream->codec_priv;
+ gint i, offset, length, num_packets;
/* start of the stream and vorbis audio or theora video, need to
* send the codec_priv data as first three packets */
- p = (guchar *) stream->codec_priv;
- offset = 3;
+ num_packets = p[0] + 1;
+ GST_DEBUG_OBJECT (demux, "%u stream headers, total length=%u bytes",
+ (guint) num_packets, stream->codec_priv_size);
+
+ offset = num_packets; /* offset to data of first packet */
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < num_packets - 1; i++) {
length = p[i + 1];
- if (gst_pad_alloc_buffer_and_set_caps (stream->pad, GST_BUFFER_OFFSET_NONE,
- length, stream->caps, &priv) == GST_FLOW_OK) {
- memcpy (GST_BUFFER_DATA (priv), &p[offset], length);
- ret = gst_pad_push (stream->pad, priv);
- if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
- return FALSE;
- }
+ GST_DEBUG_OBJECT (demux, "buffer %d: length=%u bytes", i, (guint) length);
+ if (offset + length > stream->codec_priv_size)
+ return FALSE;
+
+ if (!gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length))
+ return FALSE;
+
offset += length;
}
+
length = stream->codec_priv_size - offset;
- if (gst_pad_alloc_buffer_and_set_caps (stream->pad, GST_BUFFER_OFFSET_NONE,
- length, stream->caps, &priv) == GST_FLOW_OK) {
- memcpy (GST_BUFFER_DATA (priv), &p[offset], length);
- ret = gst_pad_push (stream->pad, priv);
- if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
- return FALSE;
- }
+ GST_DEBUG_OBJECT (demux, "buffer %d: length=%u bytes", i, (guint) length);
+ if (!gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length))
+ return FALSE;
+
return TRUE;
}
@@ -2373,6 +2435,13 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
stream->send_xiph_headers = FALSE;
}
+ if (stream->send_flac_headers) {
+ if (!gst_matroska_demux_push_flac_codec_priv_data (demux, stream)) {
+ got_error = TRUE;
+ }
+ stream->send_flac_headers = FALSE;
+ }
+
if (got_error)
break;
@@ -3044,6 +3113,7 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
g_assert (codec_name != NULL);
context->send_xiph_headers = FALSE;
+ context->send_flac_headers = FALSE;
if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC)) {
gst_riff_strf_vids *vids = NULL;
@@ -3325,6 +3395,7 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
g_assert (codec_name != NULL);
context->send_xiph_headers = FALSE;
+ context->send_flac_headers = FALSE;
if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1) ||
!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2) ||
@@ -3379,6 +3450,9 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
context->send_xiph_headers = TRUE;
/* vorbis decoder does tags */
+ } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_FLAC)) {
+ caps = gst_caps_new_simple ("audio/x-flac", NULL);
+ context->send_flac_headers = TRUE;
} else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) {
gst_riff_strf_auds *auds = NULL;
diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h
index cfc7b80d..0c05974b 100644
--- a/gst/matroska/matroska-ids.h
+++ b/gst/matroska/matroska-ids.h
@@ -156,6 +156,7 @@
#define GST_MATROSKA_CODEC_ID_AUDIO_AC3 "A_AC3"
#define GST_MATROSKA_CODEC_ID_AUDIO_DTS "A_DTS"
#define GST_MATROSKA_CODEC_ID_AUDIO_VORBIS "A_VORBIS"
+#define GST_MATROSKA_CODEC_ID_AUDIO_FLAC "A_FLAC"
#define GST_MATROSKA_CODEC_ID_AUDIO_ACM "A_MS/ACM"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG2 "A_AAC/MPEG2/"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG4 "A_AAC/MPEG4/"
@@ -254,6 +255,11 @@ typedef struct _GstMatroskaTrackContext {
* for time == 0 is not enough to detect that. Used by demuxer */
gboolean send_xiph_headers;
+ /* Special flag for Flac, for which we need to reconstruct the header
+ * buffer from the codec_priv data before sending any data, and just
+ * testing for time == 0 is not enough to detect that. Used by demuxer */
+ gboolean send_flac_headers;
+
/* Special counter for muxer to skip the first N vorbis/theora headers -
* they are put into codec private data, not muxed into the stream */
guint xiph_headers_to_skip;