summaryrefslogtreecommitdiffstats
path: root/gst
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 /gst
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.
Diffstat (limited to 'gst')
-rw-r--r--gst/matroska/matroska-demux.c118
-rw-r--r--gst/matroska/matroska-ids.h6
2 files changed, 102 insertions, 22 deletions
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;