Add C-based local matroska/EBML plugin, remove libmatroska/libebml c++ one

Original commit message from CVS:
Add C-based local matroska/EBML plugin, remove libmatroska/libebml c++ one
This commit is contained in:
Ronald S. Bultje 2003-11-21 21:34:27 +00:00
parent e21d05a300
commit 29e9ebcfda
10 changed files with 4001 additions and 18 deletions

View file

@ -287,6 +287,7 @@ GST_PLUGINS_ALL="\
intfloat \
law \
level \
matroska \
median \
mixmatrix \
mpeg1sys \
@ -956,15 +957,6 @@ GST_CHECK_FEATURE(MAD, [mad mp3 decoder], mad, [
])
AC_SUBST(MAD_LIBS)
dnl *** matroska ***
translit(dnm, m, l) AM_CONDITIONAL(USE_MATROSKA, true)
GST_CHECK_FEATURE(MATROSKA, [matroska muxer/demuxer], matroska muxer/demuxer, [
PATH_EBML([HAVE_MATROSKA=yes], [HAVE_MATROSKA=no])
if test x$HAVE_MATROSKA = xyes; then
PATH_MATROSKA(0.4.4, [HAVE_MATROSKA=yes], [HAVE_MATROSKA=no])
fi
])
dnl *** mikmod ***
translit(dnm, m, l) AM_CONDITIONAL(USE_MIKMOD, true)
GST_CHECK_FEATURE(MIKMOD, [mikmod plug-in], mikmod, [
@ -1316,6 +1308,7 @@ gst/id3/Makefile
gst/intfloat/Makefile
gst/law/Makefile
gst/level/Makefile
gst/matroska/Makefile
gst/median/Makefile
gst/mixmatrix/Makefile
gst/mpeg1sys/Makefile
@ -1401,7 +1394,6 @@ ext/libfame/Makefile
ext/libpng/Makefile
ext/mad/Makefile
ext/mas/Makefile
ext/matroska/Makefile
ext/mikmod/Makefile
ext/mpeg2dec/Makefile
ext/mplex/Makefile

View file

@ -172,12 +172,6 @@ else
MAD_DIR=
endif
if USE_MATROSKA
MATROSKA_DIR=matroska
else
MATROSKA_DIR=
endif
if USE_MIKMOD
MIKMOD_DIR=mikmod
else
@ -309,7 +303,6 @@ SUBDIRS=\
$(LIBPNG_DIR) \
$(MAD_DIR) \
$(MAS_DIR) \
$(MATROSKA_DIR) \
$(MIKMOD_DIR) \
$(MPEG2DEC_DIR) \
$(MPLEX_DIR) \
@ -357,7 +350,6 @@ DIST_SUBDIRS=\
libfame \
libpng \
mad \
matroska \
mikmod \
mpeg2dec \
mplex \

16
gst/matroska/Makefile.am Normal file
View file

@ -0,0 +1,16 @@
plugin_LTLIBRARIES = libgstmatroska.la
libgstmatroska_la_SOURCES = \
ebml-read.c \
matroska.c \
matroska-demux.c
noinst_HEADERS = \
ebml-ids.h \
ebml-read.h \
matroska-demux.h \
matroska-ids.h
libgstmatroska_la_CFLAGS = $(GST_CFLAGS)
libgstmatroska_la_LIBADD =
libgstmatroska_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

47
gst/matroska/ebml-ids.h Normal file
View file

@ -0,0 +1,47 @@
/* GStreamer EBML I/O
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* ebml-ids.h: definition of EBML data IDs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_EBML_IDS_H__
#define __GST_EBML_IDS_H__
G_BEGIN_DECLS
/* EBML version supported */
#define GST_EBML_VERSION 1
/* top-level master-IDs */
#define GST_EBML_ID_HEADER 0x1A45DFA3
/* IDs in the HEADER master */
#define GST_EBML_ID_EBMLVERSION 0x4286
#define GST_EBML_ID_EBMLREADVERSION 0x42F7
#define GST_EBML_ID_EBMLMAXIDLENGTH 0x42F2
#define GST_EBML_ID_EBMLMAXSIZELENGTH 0x42F3
#define GST_EBML_ID_DOCTYPE 0x4282
#define GST_EBML_ID_DOCTYPEVERSION 0x4287
#define GST_EBML_ID_DOCTYPEREADVERSION 0x4285
/* general EBML types */
#define GST_EBML_ID_VOID 0xEC
G_END_DECLS
#endif /* __GST_EBML_IDS_H__ */

702
gst/matroska/ebml-read.c Normal file
View file

@ -0,0 +1,702 @@
/* GStreamer EBML I/O
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* ebml-read.c: read EBML data from file/stream
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include "ebml-read.h"
#include "ebml-ids.h"
enum {
/* FILL ME */
LAST_SIGNAL
};
static void gst_ebml_read_class_init (GstEbmlReadClass *klass);
static void gst_ebml_read_init (GstEbmlRead *ebml);
static GstElementStateReturn
gst_ebml_read_change_state (GstElement *element);
static GstElementClass *parent_class = NULL;
GType
gst_ebml_read_get_type (void)
{
static GType gst_ebml_read_type = 0;
if (!gst_ebml_read_type) {
static const GTypeInfo gst_ebml_read_info = {
sizeof (GstEbmlReadClass),
NULL,
NULL,
(GClassInitFunc) gst_ebml_read_class_init,
NULL,
NULL,
sizeof (GstEbmlRead),
0,
(GInstanceInitFunc) gst_ebml_read_init,
};
gst_ebml_read_type =
g_type_register_static (GST_TYPE_ELEMENT, "GstEbmlRead",
&gst_ebml_read_info, 0);
}
return gst_ebml_read_type;
}
static void
gst_ebml_read_class_init (GstEbmlReadClass *klass)
{
GstElementClass *gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
gstelement_class->change_state = gst_ebml_read_change_state;
}
static void
gst_ebml_read_init (GstEbmlRead *ebml)
{
ebml->sinkpad = NULL;
ebml->bs = NULL;
ebml->level = NULL;
}
static GstElementStateReturn
gst_ebml_read_change_state (GstElement *element)
{
GstEbmlRead *ebml = GST_EBML_READ (element);
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_READY_TO_PAUSED:
if (!ebml->sinkpad)
return GST_STATE_FAILURE;
ebml->bs = gst_bytestream_new (ebml->sinkpad);
break;
case GST_STATE_PAUSED_TO_READY:
gst_bytestream_destroy (ebml->bs);
while (ebml->level) {
GstEbmlLevel *level = ebml->level->data;
ebml->level = g_list_remove (ebml->level, level);
g_free (level);
}
break;
default:
break;
}
if (GST_ELEMENT_CLASS (parent_class)->change_state)
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
return GST_STATE_SUCCESS;
}
/*
* Return: the amount of levels in the hierarchy that the
* current element lies higher than the previous one.
* The opposite isn't done - that's auto-done using master
* element reading.
*/
static guint
gst_ebml_read_element_level_up (GstEbmlRead *ebml)
{
guint num = 0;
guint64 pos = gst_bytestream_tell (ebml->bs);
while (ebml->level != NULL) {
GList *last = g_list_last (ebml->level);
GstEbmlLevel *level = last->data;
if (pos >= level->start + level->length) {
ebml->level = g_list_remove (ebml->level, level);
g_free (level);
num++;
} else
break;
}
return num;
}
/*
* Read: the element content data ID.
* Return: the number of bytes read or -1 on error.
*/
static gint
gst_ebml_read_element_id (GstEbmlRead *ebml,
guint32 *id,
guint *level_up)
{
guint8 *data;
gint len_mask = 0x80, read = 1, n = 1;
guint32 total;
if (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) {
/*gst_element_error (GST_ELEMENT (ebml), "Read error");*/
return -1;
}
total = data[0];
while (read <= 4 && !(total & len_mask)) {
read++;
len_mask >>= 1;
}
if (read > 4) {
gst_element_error (GST_ELEMENT (ebml),
"Invalid EBML ID size tag (0x%x)", data[0]);
return -1;
}
if (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) {
/*gst_element_error (GST_ELEMENT (ebml), "Read error");*/
return -1;
}
while (n < read)
total = (total << 8) | data[n++];
*id = total;
/* level */
if (level_up)
*level_up = gst_ebml_read_element_level_up (ebml);
return read;
}
/*
* Read: element content length.
* Return: the number of bytes read or -1 on error.
*/
static gint
gst_ebml_read_element_length (GstEbmlRead *ebml,
guint64 *length)
{
guint8 *data;
gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
guint64 total;
if (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) {
/*gst_element_error (GST_ELEMENT (ebml), "Read error");*/
return -1;
}
total = data[0];
while (read <= 8 && !(total & len_mask)) {
read++;
len_mask >>= 1;
}
if (read > 8) {
gst_element_error (GST_ELEMENT (ebml),
"Invalid EBML length size tag (0x%x)", data[0]);
return -1;
}
if ((total &= (len_mask - 1)) == len_mask - 1)
num_ffs++;
if (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) {
/*gst_element_error (GST_ELEMENT (ebml), "Read error");*/
return -1;
}
while (n < read) {
if (data[n] == 0xff)
num_ffs++;
total = (total << 8) | data[n];
n++;
}
if (!total) {
gst_element_error (GST_ELEMENT (ebml),
"Invalid length 0");
return -1;
}
if (read == num_ffs)
*length = G_MAXUINT64;
else
*length = total;
return read;
}
/*
* Read: the actual data.
* Return: the data, as a GstBuffer.
*/
static GstBuffer *
gst_ebml_read_element_data (GstEbmlRead *ebml,
guint64 length)
{
GstBuffer *buf = NULL;
if (gst_bytestream_peek (ebml->bs, &buf, length) != length) {
/*gst_element_error (GST_ELEMENT (ebml), "Read error");*/
if (buf)
gst_buffer_unref (buf);
return NULL;
}
gst_bytestream_flush_fast (ebml->bs, length);
return buf;
}
/*
* Return: the ID of the next element.
* Level_up contains the amount of levels that this
* next element lies higher than the previous one.
*/
guint32
gst_ebml_peek_id (GstEbmlRead *ebml,
guint *level_up)
{
guint32 id;
guint my_level_up;
g_return_val_if_fail (level_up != NULL, 0);
if (gst_ebml_read_element_id (ebml, &id, &my_level_up) < 0)
return 0;
if (level_up)
*level_up = my_level_up;
return id;
}
/*
* Seek to a given offset.
*/
void
gst_ebml_read_seek (GstEbmlRead *ebml,
guint64 offset)
{
gst_bytestream_seek (ebml->bs, offset, GST_SEEK_METHOD_SET);
}
/*
* Skip the next element.
*/
gboolean
gst_ebml_read_skip (GstEbmlRead *ebml)
{
gint bytes;
guint32 id;
guint64 length;
if ((bytes = gst_ebml_read_element_id (ebml, &id, NULL)) < 0)
return FALSE;
gst_bytestream_flush_fast (ebml->bs, bytes);
if ((bytes = gst_ebml_read_element_length (ebml, &length)) < 0)
return FALSE;
gst_bytestream_flush_fast (ebml->bs, bytes);
return gst_bytestream_flush (ebml->bs, length);
}
/*
* Read the next element as a GstBuffer (binary).
*/
gboolean
gst_ebml_read_buffer (GstEbmlRead *ebml,
guint32 *id,
GstBuffer **buf)
{
gint bytes;
guint64 length;
if ((bytes = gst_ebml_read_element_id (ebml, id, NULL)) < 0)
return FALSE;
gst_bytestream_flush_fast (ebml->bs, bytes);
if ((bytes = gst_ebml_read_element_length (ebml, &length)) < 0)
return FALSE;
gst_bytestream_flush_fast (ebml->bs, bytes);
return ((*buf = gst_ebml_read_element_data (ebml, length)) != NULL);
}
/*
* Read the next element as an unsigned int.
*/
gboolean
gst_ebml_read_uint (GstEbmlRead *ebml,
guint32 *id,
guint64 *num)
{
GstBuffer *buf;
guint8 *data;
guint size;
if (!gst_ebml_read_buffer (ebml, id, &buf))
return FALSE;
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
if (size < 1 || size > 8) {
gst_element_error (GST_ELEMENT (ebml),
"Invalid integer element size %d", size);
gst_buffer_unref (buf);
return FALSE;
}
*num = 0;
while (size > 0) {
*num = (*num << 8) | data[GST_BUFFER_SIZE (buf) - size];
size--;
}
gst_buffer_unref (buf);
return TRUE;
}
/*
* Read the next element as a signed int.
*/
gboolean
gst_ebml_read_sint (GstEbmlRead *ebml,
guint32 *id,
gint64 *num)
{
GstBuffer *buf;
guint8 *data;
guint size;
if (!gst_ebml_read_buffer (ebml, id, &buf))
return FALSE;
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
if (size < 1 || size > 8) {
gst_element_error (GST_ELEMENT (ebml),
"Invalid integer element size %d", size);
gst_buffer_unref (buf);
return FALSE;
}
*num = 0;
while (size > 0) {
*num = (*num << 8) | data[GST_BUFFER_SIZE (buf) - size];
size--;
}
/* make signed */
*num -= (1LL << ((8 * GST_BUFFER_SIZE (buf)) - 1));
gst_buffer_unref (buf);
return TRUE;
}
/*
* Read the next element as a float.
*/
gboolean
gst_ebml_read_float (GstEbmlRead *ebml,
guint32 *id,
gdouble *num)
{
GstBuffer *buf;
guint8 *data;
guint size;
if (!gst_ebml_read_buffer (ebml, id, &buf))
return FALSE;
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
if (size != 4 && size != 8 && size != 10) {
gst_element_error (GST_ELEMENT (ebml),
"Invalid float element size %d", size);
gst_buffer_unref (buf);
return FALSE;
}
if (size == 10) {
gst_element_error (GST_ELEMENT (ebml),
"FIXME! 10-byte floats unimplemented");
gst_buffer_unref (buf);
return FALSE;
}
if (size == 4) {
gfloat f;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
f = * (gfloat *) data;
#else
while (size > 0) {
((guint8 *) &f)[size - 1] = data[4 - size];
size--;
}
#endif
*num = f;
} else {
gdouble d;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
d = * (gdouble *) data;
#else
while (size > 0) {
((guint8 *) &d)[size - 1] = data[8 - size];
size--;
}
#endif
*num = d;
}
gst_buffer_unref (buf);
return TRUE;
}
/*
* Read the next element as an ASCII string.
*/
gboolean
gst_ebml_read_ascii (GstEbmlRead *ebml,
guint32 *id,
gchar **str)
{
GstBuffer *buf;
if (!gst_ebml_read_buffer (ebml, id, &buf))
return FALSE;
*str = g_malloc (GST_BUFFER_SIZE (buf) + 1);
memcpy (*str, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
(*str)[GST_BUFFER_SIZE (buf)] = '\0';
gst_buffer_unref (buf);
return TRUE;
}
/*
* Read the next element as a UTF-8 string.
*/
gboolean
gst_ebml_read_utf8 (GstEbmlRead *ebml,
guint32 *id,
gchar **str)
{
return gst_ebml_read_ascii (ebml, id, str);
}
/*
* Read the next element as a date (nanoseconds since 1/1/2000).
*/
gboolean
gst_ebml_read_date (GstEbmlRead *ebml,
guint32 *id,
gint64 *date)
{
return gst_ebml_read_sint (ebml, id, date);
}
/*
* Read the next element, but only the header. The contents
* are supposed to be sub-elements which can be read separately.
*/
gboolean
gst_ebml_read_master (GstEbmlRead *ebml,
guint32 *id)
{
gint bytes;
guint64 length;
GstEbmlLevel *level;
if ((bytes = gst_ebml_read_element_id (ebml, id, NULL)) < 0)
return FALSE;
gst_bytestream_flush_fast (ebml->bs, bytes);
if ((bytes = gst_ebml_read_element_length (ebml, &length)) < 0)
return FALSE;
gst_bytestream_flush_fast (ebml->bs, bytes);
/* remember level */
level = g_new (GstEbmlLevel, 1);
level->start = gst_bytestream_tell (ebml->bs);
level->length = length;
ebml->level = g_list_append (ebml->level, level);
return TRUE;
}
/*
* Read the next element as binary data.
*/
gboolean
gst_ebml_read_binary (GstEbmlRead *ebml,
guint32 *id,
guint8 **binary,
guint64 *length)
{
GstBuffer *buf;
if (!gst_ebml_read_buffer (ebml, id, &buf))
return FALSE;
*length = GST_BUFFER_SIZE (buf);
*binary = g_memdup (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
gst_buffer_unref (buf);
return TRUE;
}
/*
* Read an EBML header.
*/
gboolean
gst_ebml_read_header (GstEbmlRead *ebml,
gchar **doctype,
guint *version)
{
/* this function is the first to be called */
guint32 id;
guint level_up;
/* default init */
if (doctype)
*doctype = NULL;
if (version)
*version = 1;
if (!(id = gst_ebml_peek_id (ebml, &level_up)))
return FALSE;
if (level_up != 0 || id != GST_EBML_ID_HEADER) {
gst_element_error (GST_ELEMENT (ebml), "Not a EBML file");
return FALSE;
}
if (!gst_ebml_read_master (ebml, &id))
return FALSE;
g_assert (id == GST_EBML_ID_HEADER);
while (TRUE) {
if (!(id = gst_ebml_peek_id (ebml, &level_up)))
return FALSE;
/* end-of-header */
if (level_up)
break;
switch (id) {
/* is our read version uptodate? */
case GST_EBML_ID_EBMLREADVERSION: {
guint64 num;
if (!gst_ebml_read_uint (ebml, &id, &num))
return FALSE;
g_assert (id == GST_EBML_ID_EBMLREADVERSION);
if (num != GST_EBML_VERSION)
return FALSE;
break;
}
/* we only handle 8 byte lengths at max */
case GST_EBML_ID_EBMLMAXSIZELENGTH: {
guint64 num;
if (!gst_ebml_read_uint (ebml, &id, &num))
return FALSE;
g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH);
if (num != sizeof (guint64))
return FALSE;
break;
}
/* we handle 4 byte IDs at max */
case GST_EBML_ID_EBMLMAXIDLENGTH: {
guint64 num;
if (!gst_ebml_read_uint (ebml, &id, &num))
return FALSE;
g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH);
if (num != sizeof (guint32))
return FALSE;
break;
}
case GST_EBML_ID_DOCTYPE: {
gchar *text;
if (!gst_ebml_read_ascii (ebml, &id, &text))
return FALSE;
g_assert (id == GST_EBML_ID_DOCTYPE);
if (doctype) {
if (doctype)
g_free (*doctype);
*doctype = text;
} else
g_free (text);
break;
}
case GST_EBML_ID_DOCTYPEREADVERSION: {
guint64 num;
if (!gst_ebml_read_uint (ebml, &id, &num))
return FALSE;
g_assert (id == GST_EBML_ID_DOCTYPEREADVERSION);
if (version)
*version = num;
break;
}
default:
GST_WARNING ("Unknown data type 0x%x in EBML header (ignored)", id);
/* pass-through */
/* we ignore these two, as they don't tell us anything we care about */
case GST_EBML_ID_VOID:
case GST_EBML_ID_EBMLVERSION:
case GST_EBML_ID_DOCTYPEVERSION:
if (!gst_ebml_read_skip (ebml))
return FALSE;
break;
}
}
return TRUE;
}

102
gst/matroska/ebml-read.h Normal file
View file

@ -0,0 +1,102 @@
/* GStreamer EBML I/O
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* ebml-read.c: read EBML data from file/stream
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_EBML_READ_H__
#define __GST_EBML_READ_H__
#include <glib.h>
#include <gst/gst.h>
#include <gst/bytestream/bytestream.h>
G_BEGIN_DECLS
#define GST_TYPE_EBML_READ \
(gst_ebml_read_get_type ())
#define GST_EBML_READ(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EBML_READ, GstEbmlRead))
#define GST_EBML_READ_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_EBML_READ, GstEbmlReadClass))
#define GST_IS_EBML_READ(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EBML_READ))
#define GST_IS_EBML_READ_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_EBML_READ))
#define GST_EBML_READ_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_EBML_READ, GstEbmlReadClass))
typedef struct _GstEbmlLevel {
guint64 start,
length;
} GstEbmlLevel;
typedef struct _GstEbmlRead {
GstElement parent;
GstPad *sinkpad;
GstByteStream *bs;
GList *level;
} GstEbmlRead;
typedef struct _GstEbmlReadClass {
GstElementClass parent;
} GstEbmlReadClass;
GType gst_ebml_read_get_type (void);
guint32 gst_ebml_peek_id (GstEbmlRead *ebml,
guint *level_up);
void gst_ebml_read_seek (GstEbmlRead *ebml,
guint64 offset);
gboolean gst_ebml_read_skip (GstEbmlRead *ebml);
gboolean gst_ebml_read_buffer (GstEbmlRead *ebml,
guint32 *id,
GstBuffer **buf);
gboolean gst_ebml_read_uint (GstEbmlRead *ebml,
guint32 *id,
guint64 *num);
gboolean gst_ebml_read_sint (GstEbmlRead *ebml,
guint32 *id,
gint64 *num);
gboolean gst_ebml_read_float (GstEbmlRead *ebml,
guint32 *id,
gdouble *num);
gboolean gst_ebml_read_ascii (GstEbmlRead *ebml,
guint32 *id,
gchar **str);
gboolean gst_ebml_read_utf8 (GstEbmlRead *ebml,
guint32 *id,
gchar **str);
gboolean gst_ebml_read_date (GstEbmlRead *ebml,
guint32 *id,
gint64 *date);
gboolean gst_ebml_read_master (GstEbmlRead *ebml,
guint32 *id);
gboolean gst_ebml_read_binary (GstEbmlRead *ebml,
guint32 *id,
guchar **binary,
guint64 *length);
gboolean gst_ebml_read_header (GstEbmlRead *read,
gchar **doctype,
guint *version);
G_END_DECLS
#endif /* __GST_EBML_READ_H__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,102 @@
/* GStreamer Matroska muxer/demuxer
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* matroska-demux.h: matroska file/stream demuxer definition
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_MATROSKA_DEMUX_H__
#define __GST_MATROSKA_DEMUX_H__
#include <gst/gst.h>
#include <gst/bytestream/bytestream.h>
#include "ebml-read.h"
#include "matroska-ids.h"
G_BEGIN_DECLS
#define GST_TYPE_MATROSKA_DEMUX \
(gst_matroska_demux_get_type ())
#define GST_MATROSKA_DEMUX(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MATROSKA_DEMUX, GstMatroskaDemux))
#define GST_MATROSKA_DEMUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MATROSKA_DEMUX, GstMatroskaDemux))
#define GST_IS_MATROSKA_DEMUX(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MATROSKA_DEMUX))
#define GST_IS_MATROSKA_DEMUX_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MATROSKA_DEMUX))
#define GST_MATROSKA_DEMUX_MAX_STREAMS 64
typedef enum {
GST_MATROSKA_DEMUX_STATE_START,
GST_MATROSKA_DEMUX_STATE_HEADER,
GST_MATROSKA_DEMUX_STATE_DATA
} GstMatroskaDemuxState;
typedef struct _GstMatroskaDemuxIndex {
guint64 pos; /* of the corresponding *cluster*! */
guint16 track; /* reference to 'num' */
guint64 time; /* in nanoseconds */
} GstMatroskaDemuxIndex;
typedef struct _GstMatroskaDemux {
GstEbmlRead parent;
/* pads */
GstPad *sinkpad;
GstMatroskaTrackContext *src[GST_MATROSKA_DEMUX_MAX_STREAMS];
guint num_streams,
num_v_streams, num_a_streams, num_t_streams;
/* metadata */
GstCaps *metadata,
*streaminfo;
gchar *muxing_app, *writing_app;
gint64 created;
/* state */
GstMatroskaDemuxState state;
guint level_up;
/* a cue (index) table */
GstMatroskaIndex *index;
guint num_indexes;
/* timescale in the file */
guint64 time_scale;
/* length, position (time, ns) */
guint64 duration,
pos;
/* a possible pending seek */
guint64 seek_pending;
} GstMatroskaDemux;
typedef struct _GstMatroskaDemuxClass {
GstEbmlReadClass parent;
} GstMatroskaDemuxClass;
GType gst_matroska_demux_get_type (void);
gboolean gst_matroska_demux_plugin_init (GstPlugin *plugin);
G_END_DECLS
#endif /* __GST_MATROSKA_DEMUX_H__ */

237
gst/matroska/matroska-ids.h Normal file
View file

@ -0,0 +1,237 @@
/* GStreamer Matroska muxer/demuxer
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* matroska-ids.h: matroska file/stream data IDs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_MATROSKA_IDS_H__
#define __GST_MATROSKA_IDS_H__
#include "ebml-ids.h"
/*
* EBML element IDs. max. 32-bit.
*/
/* toplevel segment */
#define GST_MATROSKA_ID_SEGMENT 0x18538067
/* matroska top-level master IDs */
#define GST_MATROSKA_ID_INFO 0x1549A966
#define GST_MATROSKA_ID_TRACKS 0x1654AE6B
#define GST_MATROSKA_ID_CUES 0x1C53BB6B
#define GST_MATROSKA_ID_TAGS 0x1254C367
#define GST_MATROSKA_ID_SEEKHEAD 0x114D9B74
#define GST_MATROSKA_ID_CLUSTER 0x1F43B675
/* IDs in the info master */
#define GST_MATROSKA_ID_TIMECODESCALE 0x2AD7B1
#define GST_MATROSKA_ID_DURATION 0x4489
#define GST_MATROSKA_ID_WRITINGAPP 0x5741
#define GST_MATROSKA_ID_MUXINGAPP 0x4D80
#define GST_MATROSKA_ID_DATEUTC 0x4461
/* ID in the tracks master */
#define GST_MATROSKA_ID_TRACKENTRY 0xAE
/* IDs in the trackentry master */
#define GST_MATROSKA_ID_TRACKNUMBER 0xD7
#define GST_MATROSKA_ID_TRACKUID 0x73C5
#define GST_MATROSKA_ID_TRACKTYPE 0x83
#define GST_MATROSKA_ID_TRACKAUDIO 0xE1
#define GST_MATROSKA_ID_TRACKVIDEO 0xE0
#define GST_MATROSKA_ID_CODECID 0x86
#define GST_MATROSKA_ID_CODECPRIVATE 0x63A2
#define GST_MATROSKA_ID_CODECNAME 0x258688
#define GST_MATROSKA_ID_CODECINFOURL 0x3B4040
#define GST_MATROSKA_ID_CODECDOWNLOADURL 0x26B240
#define GST_MATROSKA_ID_TRACKNAME 0x536E
#define GST_MATROSKA_ID_TRACKLANGUAGE 0x22B59C
#define GST_MATROSKA_ID_TRACKFLAGENABLED 0xB9
#define GST_MATROSKA_ID_TRACKFLAGDEFAULT 0x88
#define GST_MATROSKA_ID_TRACKFLAGLACING 0x9C
#define GST_MATROSKA_ID_TRACKMINCACHE 0x6DE7
#define GST_MATROSKA_ID_TRACKMAXCACHE 0x6DF8
#define GST_MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383
/* IDs in the trackvideo master */
#define GST_MATROSKA_ID_VIDEOFRAMERATE 0x2383E3
#define GST_MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0
#define GST_MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA
#define GST_MATROSKA_ID_VIDEOPIXELWIDTH 0xB0
#define GST_MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA
#define GST_MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A
#define GST_MATROSKA_ID_VIDEOSTEREOMODE 0x53B9
#define GST_MATROSKA_ID_VIDEOASPECTRATIO 0x54B3
#define GST_MATROSKA_ID_VIDEOCOLOURSPACE 0x2EB524
/* IDs in the trackaudio master */
#define GST_MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
#define GST_MATROSKA_ID_AUDIOBITDEPTH 0x6264
#define GST_MATROSKA_ID_AUDIOCHANNELS 0x9F
/* ID in the cues master */
#define GST_MATROSKA_ID_POINTENTRY 0xBB
/* IDs in the pointentry master */
#define GST_MATROSKA_ID_CUETIME 0xB3
#define GST_MATROSKA_ID_CUETRACKPOSITION 0xB7
/* IDs in the cuetrackposition master */
#define GST_MATROSKA_ID_CUETRACK 0xF7
#define GST_MATROSKA_ID_CUECLUSTERPOSITION 0xF1
/* IDs in the tags master */
/* TODO */
/* IDs in the seekhead master */
#define GST_MATROSKA_ID_SEEKENTRY 0x4DBB
/* IDs in the seekpoint master */
#define GST_MATROSKA_ID_SEEKID 0x53AB
#define GST_MATROSKA_ID_SEEKPOSITION 0x53AC
/* IDs in the cluster master */
#define GST_MATROSKA_ID_CLUSTERTIMECODE 0xE7
#define GST_MATROSKA_ID_BLOCKGROUP 0xA0
/* IDs in the blockgroup master */
#define GST_MATROSKA_ID_BLOCK 0xA1
#define GST_MATROSKA_ID_BLOCKDURATION 0x9B
/*
* Matroska Codec IDs. Strings.
*/
#define GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC "V_MS/VFW/FOURCC"
#define GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED "V_UNCOMPRESSED"
#define GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP "V_MPEG4/ISO/SP"
#define GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP "V_MPEG4/ISO/ASP"
#define GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AP "V_MPEG4/ISO/AP"
#define GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3 "V_MPEG4/MS/V3"
#define GST_MATROSKA_CODEC_ID_VIDEO_MPEG1 "V_MPEG1"
#define GST_MATROSKA_CODEC_ID_VIDEO_MPEG2 "V_MPEG2"
#define GST_MATROSKA_CODEC_ID_VIDEO_MJPEG "V_MJPEG"
/* TODO: Real/Quicktime */
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1 "A_MPEG/L1"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2 "A_MPEG/L2"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3 "A_MPEG/L3"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE "A_PCM/INT/BIG"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE "A_PCM/INT/LIT"
#define GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT "A_PCM/FLOAT/IEEE"
#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_ACM "A_MS/ACM"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG2 "A_AAC/MPEG2/"
#define GST_MATROSKA_CODEC_ID_AUDIO_MPEG4 "A_AAC/MPEG4/"
/* TODO: AC3-9/10, Real, Musepack, Quicktime */
/*
* Enumerations for various types (mapping from binary
* value to what it actually means).
*/
typedef enum {
GST_MATROSKA_TRACK_TYPE_VIDEO = 0x1,
GST_MATROSKA_TRACK_TYPE_AUDIO = 0x2,
GST_MATROSKA_TRACK_TYPE_COMPLEX = 0x3,
GST_MATROSKA_TRACK_TYPE_LOGO = 0x10,
GST_MATROSKA_TRACK_TYPE_SUBTITLE = 0x11,
GST_MATROSKA_TRACK_TYPE_CONTROL = 0x20,
} GstMatroskaTrackType;
typedef enum {
GST_MATROSKA_EYE_MODE_MONO = 0x0,
GST_MATROSKA_EYE_MODE_RIGHT = 0x1,
GST_MATROSKA_EYE_MODE_LEFT = 0x2,
GST_MATROSKA_EYE_MODE_BOTH = 0x3,
} GstMatroskaEyeMode;
typedef enum {
GST_MATROSKA_ASPECT_RATIO_MODE_FREE = 0x0,
GST_MATROSKA_ASPECT_RATIO_MODE_KEEP = 0x1,
GST_MATROSKA_ASPECT_RATIO_MODE_FIXED = 0x2,
} GstMatroskaAspectRatioMode;
/*
* These aren't in any way "matroska-form" things,
* it's just something I use in the muxer/demuxer.
*/
typedef enum {
GST_MATROSKA_TRACK_ENABLED = (1<<0),
GST_MATROSKA_TRACK_DEFAULT = (1<<1),
GST_MATROSKA_TRACK_LACING = (1<<2),
GST_MATROSKA_TRACK_SHIFT = (1<<16)
} GstMatroskaTrackFlags;
typedef enum {
GST_MATROSKA_VIDEOTRACK_INTERLACED = (GST_MATROSKA_TRACK_SHIFT<<0)
} GstMatroskaVideoTrackFlags;
typedef struct _GstMatroskaTrackContext {
GstPad *pad;
guint index;
/* some often-used info */
gchar *codec_id, *codec_name, *name, *language;
gpointer codec_priv;
guint codec_priv_size;
GstMatroskaTrackType type;
guint uid, num;
GstMatroskaTrackFlags flags;
guint64 default_duration;
} GstMatroskaTrackContext;
typedef struct _GstMatroskaTrackVideoContext {
GstMatroskaTrackContext parent;
guint pixel_width, pixel_height,
display_width, display_height;
GstMatroskaEyeMode eye_mode;
GstMatroskaAspectRatioMode asr_mode;
guint32 fourcc;
} GstMatroskaTrackVideoContext;
typedef struct _GstMatroskaTrackAudioContext {
GstMatroskaTrackContext parent;
guint samplerate, channels, bitdepth;
} GstMatroskaTrackAudioContext;
typedef struct _GstMatroskaTrackComplexContext {
GstMatroskaTrackContext parent;
/* nothing special goes here, apparently */
} GstMatroskaTrackComplexContext;
typedef struct _GstMatroskaTrackSubtitleContext {
GstMatroskaTrackContext parent;
/* or here... */
} GstMatroskaTrackSubtitleContext;
typedef struct _GstMatroskaIndex {
guint64 pos; /* of the corresponding *cluster*! */
guint16 track; /* reference to 'num' */
guint64 time; /* in nanoseconds */
} GstMatroskaIndex;
#endif /* __GST_MATROSKA_IDS_H__ */

47
gst/matroska/matroska.c Normal file
View file

@ -0,0 +1,47 @@
/* GStreamer Matroska muxer/demuxer
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* matroska.c: plugin loader
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "matroska-demux.h"
#include "matroska-mux.h"
static gboolean
plugin_init (GstPlugin *plugin)
{
return (gst_matroska_demux_plugin_init (plugin) &&
gst_matroska_mux_plugin_init (plugin));
}
GST_PLUGIN_DEFINE (
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"matroska",
"Matroska stream handling",
plugin_init,
VERSION,
"LGPL",
GST_COPYRIGHT,
GST_PACKAGE,
GST_ORIGIN
)