diff options
author | Tim-Philipp Müller <tim@centricular.net> | 2006-09-04 15:06:25 +0000 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.net> | 2006-09-04 15:06:25 +0000 |
commit | a0fa3b2917891bc36e3c186bc2d5389233571331 (patch) | |
tree | 544e7c0721608fbfa182ce0fa47eaf2c58f815ac /gst | |
parent | fc559fff48fc72e04aca551519d5bf8dfef8d877 (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.c | 118 | ||||
-rw-r--r-- | gst/matroska/matroska-ids.h | 6 |
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; |