summaryrefslogtreecommitdiffstats
path: root/gst/matroska/ebml-write.c
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.net>2005-10-14 12:43:30 +0000
committerTim-Philipp Müller <tim@centricular.net>2005-10-14 12:43:30 +0000
commit22b9a5cd4310a0c4b4ab1508c0ac8fb6a951f061 (patch)
tree7425a287d6c908eb1acda5b99793ac69343d7a32 /gst/matroska/ebml-write.c
parentfb495736bc531080df1a7874d7ef3b94679d25a9 (diff)
Port matroska muxer to 0.9 (#318847).
Original commit message from CVS: Reviewed by: Tim-Philipp Müller <tim at centricular dot net> * configure.ac: * gst/matroska/Makefile.am: * gst/matroska/ebml-ids.h: * gst/matroska/ebml-write.c: * gst/matroska/ebml-write.h: * gst/matroska/matroska-ids.h: * gst/matroska/matroska-mux.c: * gst/matroska/matroska-mux.h: * gst/matroska/matroska.c: (plugin_init): Port matroska muxer to 0.9 (#318847).
Diffstat (limited to 'gst/matroska/ebml-write.c')
-rw-r--r--gst/matroska/ebml-write.c394
1 files changed, 292 insertions, 102 deletions
diff --git a/gst/matroska/ebml-write.c b/gst/matroska/ebml-write.c
index 139c4d0b..27bc6b55 100644
--- a/gst/matroska/ebml-write.c
+++ b/gst/matroska/ebml-write.c
@@ -1,5 +1,6 @@
/* GStreamer EBML I/O
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * (c) 2005 Michal Benes <michal.benes@xeris.cz>
*
* ebml-write.c: write EBML data to file/stream
*
@@ -28,85 +29,116 @@
#include "ebml-write.h"
#include "ebml-ids.h"
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-static void gst_ebml_write_class_init (GstEbmlWriteClass * klass);
-static void gst_ebml_write_init (GstEbmlWrite * ebml);
-static GstStateChangeReturn gst_ebml_write_change_state (GstElement * element,
- GstStateChange transition);
+GST_DEBUG_CATEGORY_STATIC (gst_ebml_write_debug);
+#define GST_CAT_DEFAULT gst_ebml_write_debug
-static GstElementClass *parent_class = NULL;
+#define _do_init(thing) \
+ GST_DEBUG_CATEGORY_INIT (gst_ebml_write_debug, "GstEbmlWrite", 0, "Write EBML structured data")
+GST_BOILERPLATE_FULL (GstEbmlWrite, gst_ebml_write, GstObject, GST_TYPE_OBJECT,
+ _do_init)
+
+ static void gst_ebml_write_finalize (GObject * object);
-GType
-gst_ebml_write_get_type (void)
-{
- static GType gst_ebml_write_type = 0;
-
- if (!gst_ebml_write_type) {
- static const GTypeInfo gst_ebml_write_info = {
- sizeof (GstEbmlWriteClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_ebml_write_class_init,
- NULL,
- NULL,
- sizeof (GstEbmlWrite),
- 0,
- (GInstanceInitFunc) gst_ebml_write_init,
- };
-
- gst_ebml_write_type =
- g_type_register_static (GST_TYPE_ELEMENT, "GstEbmlWrite",
- &gst_ebml_write_info, 0);
- }
- return gst_ebml_write_type;
+ static void gst_ebml_write_base_init (gpointer g_class)
+{
}
static void
gst_ebml_write_class_init (GstEbmlWriteClass * klass)
{
- GstElementClass *gstelement_class = (GstElementClass *) klass;
-
- parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+ GObjectClass *object = G_OBJECT_CLASS (klass);
- gstelement_class->change_state = gst_ebml_write_change_state;
+ object->finalize = gst_ebml_write_finalize;
}
static void
-gst_ebml_write_init (GstEbmlWrite * ebml)
+gst_ebml_write_init (GstEbmlWrite * ebml, GstEbmlWriteClass * klass)
{
ebml->srcpad = NULL;
ebml->pos = 0;
ebml->cache = NULL;
+ ebml->cache_size = 0;
+}
+
+static void
+gst_ebml_write_finalize (GObject * object)
+{
+ GstEbmlWrite *ebml = GST_EBML_WRITE (object);
+
+ gst_object_unref (ebml->srcpad);
+
+ GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
+}
+
+
+/**
+ * gst_ebml_write_new:
+ * @srcpad: Source pad to which the output will be pushed.
+ *
+ * Creates a new #GstEbmlWrite.
+ *
+ * Returns: a new #GstEbmlWrite
+ */
+GstEbmlWrite *
+gst_ebml_write_new (GstPad * srcpad)
+{
+ GstEbmlWrite *ebml =
+ GST_EBML_WRITE (g_object_new (GST_TYPE_EBML_WRITE, NULL));
+
+ ebml->srcpad = gst_object_ref (srcpad);
+
+ gst_ebml_write_reset (ebml);
+
+ return ebml;
}
-static GstStateChangeReturn
-gst_ebml_write_change_state (GstElement * element, GstStateChange transition)
+
+/**
+ * gst_ebml_write_reset:
+ * @ebml: a #GstEbmlWrite.
+ *
+ * Reset internal state of #GstEbmlWrite.
+ */
+void
+gst_ebml_write_reset (GstEbmlWrite * ebml)
{
- GstEbmlWrite *ebml = GST_EBML_WRITE (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- ebml->pos = 0;
- break;
- default:
- break;
+ ebml->pos = 0;
+
+ if (ebml->cache) {
+ gst_buffer_unref (ebml->cache);
+ ebml->cache = NULL;
}
+ ebml->cache_size = 0;
+ ebml->last_write_result = GST_FLOW_OK;
+}
- if (GST_ELEMENT_CLASS (parent_class)->change_state)
- return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
- return GST_STATE_CHANGE_SUCCESS;
+/**
+ * gst_ebml_last_write_result:
+ * @ebml: a #GstEbmlWrite.
+ *
+ * Returns: GST_FLOW_OK if there was not write error since the last call of
+ * gst_ebml_last_write_result or code of the error.
+ */
+GstFlowReturn
+gst_ebml_last_write_result (GstEbmlWrite * ebml)
+{
+ GstFlowReturn res = ebml->last_write_result;
+
+ ebml->last_write_result = GST_FLOW_OK;
+
+ return res;
}
-/*
- * Caching.
+
+/**
+ * gst_ebml_write_set_cache:
+ * @ebml: a #GstEbmlWrite.
+ * @size: size of the cache.
+ * Create a cache.
*
* The idea is that you use this for writing a lot
* of small elements. This will just "queue" all of
@@ -114,7 +146,6 @@ gst_ebml_write_change_state (GstElement * element, GstStateChange transition)
* at once. This saves memory and time for buffer
* allocation and init, and it looks better.
*/
-
void
gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
{
@@ -124,11 +155,18 @@ gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
g_return_if_fail (ebml->cache == NULL);
ebml->cache = gst_buffer_new_and_alloc (size);
+ ebml->cache_size = size;
GST_BUFFER_SIZE (ebml->cache) = 0;
GST_BUFFER_OFFSET (ebml->cache) = ebml->pos;
ebml->handled = 0;
}
+/**
+ * gst_ebml_write_flush_cache:
+ * @ebml: a #GstEbmlWrite.
+ *
+ * Flush the cache.
+ */
void
gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
{
@@ -141,16 +179,25 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
g_assert (GST_BUFFER_SIZE (ebml->cache) +
GST_BUFFER_OFFSET (ebml->cache) == ebml->pos);
- gst_pad_push (ebml->srcpad, GST_DATA (ebml->cache));
+ if (ebml->last_write_result == GST_FLOW_OK)
+ ebml->last_write_result = gst_pad_push (ebml->srcpad, ebml->cache);
+
ebml->cache = NULL;
+ ebml->cache_size = 0;
ebml->handled = 0;
}
-/*
- * One-element buffer, in case of no cache. If there is
+
+/**
+ * gst_ebml_write_element_new:
+ * @ebml: a #GstEbmlWrite.
+ * @size: size of the requested buffer.
+ *
+ * Create a buffer for one element. If there is
* a cache, use that instead.
+ *
+ * Returns: A new #GstBuffer.
*/
-
static GstBuffer *
gst_ebml_write_element_new (GstEbmlWrite * ebml, guint size)
{
@@ -162,7 +209,7 @@ gst_ebml_write_element_new (GstEbmlWrite * ebml, guint size)
/* prefer cache */
if (ebml->cache) {
- if (GST_BUFFER_MAXSIZE (ebml->cache) - GST_BUFFER_SIZE (ebml->cache) < size) {
+ if (ebml->cache_size - GST_BUFFER_SIZE (ebml->cache) < size) {
GST_LOG ("Cache available, but too small. Clearing...");
gst_ebml_write_flush_cache (ebml);
} else {
@@ -177,10 +224,14 @@ gst_ebml_write_element_new (GstEbmlWrite * ebml, guint size)
return buf;
}
-/*
+
+/**
+ * gst_ebml_write_element_id:
+ * @buf: Buffer to which id should be written.
+ * @id: Element ID that should be written.
+ *
* Write element ID into a buffer.
*/
-
static void
gst_ebml_write_element_id (GstBuffer * buf, guint32 id)
{
@@ -208,29 +259,38 @@ gst_ebml_write_element_id (GstBuffer * buf, guint32 id)
}
}
-/*
+
+/**
+ * gst_ebml_write_element_size:
+ * @buf: #GstBuffer to which size should be written.
+ * @size: Element length.
+ *
* Write element length into a buffer.
*/
-
static void
gst_ebml_write_element_size (GstBuffer * buf, guint64 size)
{
guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
guint bytes = 1, mask = 0x80;
- /* how many bytes? */
- while ((size >> ((bytes - 1) * 8)) >= mask && bytes <= 8) {
- mask >>= 1;
- bytes++;
- }
+ if (size != GST_EBML_SIZE_UNKNOWN) {
+ /* how many bytes? - use mask-1 because an all-1 bitset is not allowed */
+ while ((size >> ((bytes - 1) * 8)) >= (mask - 1) && bytes <= 8) {
+ mask >>= 1;
+ bytes++;
+ }
- /* if invalid size, use max. */
- if (bytes > 8) {
- GST_WARNING ("Invalid size, maximizing");
+ /* if invalid size, use max. */
+ if (bytes > 8) {
+ GST_WARNING ("Invalid size, writing size unknown");
+ mask = 0x01;
+ bytes = 8;
+ /* Now here's a real FIXME: we cannot read those yet! */
+ size = GST_EBML_SIZE_UNKNOWN;
+ }
+ } else {
mask = 0x01;
bytes = 8;
- /* Now here's a real FIXME: we cannot read those yet! */
- size = G_GINT64_CONSTANT (0x00ffffffffffffff);
}
/* write out, BE, with length size marker */
@@ -243,10 +303,15 @@ gst_ebml_write_element_size (GstBuffer * buf, guint64 size)
}
}
-/*
+
+/**
+ * gst_ebml_write_element_data:
+ * @buf: #GstBuffer to which data should be written.
+ * @write: Data that should be written.
+ * @length: Length of the data.
+ *
* Write element data into a buffer.
*/
-
static void
gst_ebml_write_element_data (GstBuffer * buf, guint8 * write, guint64 length)
{
@@ -256,10 +321,14 @@ gst_ebml_write_element_data (GstBuffer * buf, guint8 * write, guint64 length)
GST_BUFFER_SIZE (buf) += length;
}
-/*
+
+/**
+ * gst_ebml_write_element_push:
+ * @ebml: #GstEbmlWrite
+ * @buf: #GstBuffer to be written.
+ *
* Write out buffer by moving it to the next element.
*/
-
static void
gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf)
{
@@ -276,25 +345,30 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf)
return;
}
- gst_pad_push (ebml->srcpad, GST_DATA (buf));
+ if (ebml->last_write_result == GST_FLOW_OK)
+ ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
}
-/*
+
+/**
+ * gst_ebml_write_seek:
+ * @ebml: #GstEbmlWrite
+ * @pos: Seek position.
+ *
* Seek.
*/
-
void
gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
{
GstEvent *seek;
+ GstPad *peer_pad;
/* Cache seeking. A bit dangerous, we assume the client writer
* knows what he's doing... */
if (ebml->cache) {
/* within bounds? */
if (pos >= GST_BUFFER_OFFSET (ebml->cache) &&
- pos <
- GST_BUFFER_OFFSET (ebml->cache) + GST_BUFFER_MAXSIZE (ebml->cache)) {
+ pos < GST_BUFFER_OFFSET (ebml->cache) + ebml->cache_size) {
GST_BUFFER_SIZE (ebml->cache) = pos - GST_BUFFER_OFFSET (ebml->cache);
if (ebml->pos > pos)
ebml->handled -= ebml->pos - pos;
@@ -307,15 +381,27 @@ gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
}
}
- seek = gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET, pos);
- gst_pad_push (ebml->srcpad, GST_DATA (seek));
+ seek = gst_event_new_newsegment (FALSE, 1.0, GST_FORMAT_BYTES,
+ pos, -1, GST_CLOCK_TIME_NONE);
+ peer_pad = GST_PAD_PEER (ebml->srcpad);
+ if (peer_pad) {
+ gst_pad_send_event (peer_pad, seek);
+ } else {
+ GST_WARNING_OBJECT (ebml, "Can not seek: no peer pad");
+ }
+
ebml->pos = pos;
}
-/*
- * Get no. bytes needed to write a uint.
- */
+/**
+ * gst_ebml_write_get_uint_size:
+ * @num: Number to be encoded.
+ *
+ * Get number of bytes needed to write a uint.
+ *
+ * Returns: Encoded uint length.
+ */
static guint
gst_ebml_write_get_uint_size (guint64 num)
{
@@ -330,10 +416,14 @@ gst_ebml_write_get_uint_size (guint64 num)
}
-/*
+/**
+ * gst_ebml_write_set_uint:
+ * @buf: #GstBuffer to which ithe number should be written.
+ * @num: Number to be written.
+ * @size: Encoded number length.
+ *
* Write an uint into a buffer.
*/
-
static void
gst_ebml_write_set_uint (GstBuffer * buf, guint64 num, guint size)
{
@@ -347,10 +437,15 @@ gst_ebml_write_set_uint (GstBuffer * buf, guint64 num, guint size)
}
}
-/*
- * Data type wrappers.
- */
+/**
+ * gst_ebml_write_uint:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ * @num: Number to be written.
+ *
+ * Write uint element.
+ */
void
gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num)
{
@@ -364,6 +459,15 @@ gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num)
gst_ebml_write_element_push (ebml, buf);
}
+
+/**
+ * gst_ebml_write_sint:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ * @num: Number to be written.
+ *
+ * Write sint element.
+ */
void
gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
{
@@ -392,6 +496,15 @@ gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
gst_ebml_write_element_push (ebml, buf);
}
+
+/**
+ * gst_ebml_write_float:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ * @num: Number to be written.
+ *
+ * Write float element.
+ */
void
gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
{
@@ -413,6 +526,15 @@ gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
gst_ebml_write_element_push (ebml, buf);
}
+
+/**
+ * gst_ebml_write_ascii:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ * @str: String to be written.
+ *
+ * Write string element.
+ */
void
gst_ebml_write_ascii (GstEbmlWrite * ebml, guint32 id, const gchar * str)
{
@@ -425,25 +547,49 @@ gst_ebml_write_ascii (GstEbmlWrite * ebml, guint32 id, const gchar * str)
gst_ebml_write_element_push (ebml, buf);
}
+
+/**
+ * gst_ebml_write_utf8:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ * @str: String to be written.
+ *
+ * Write utf8 encoded string element.
+ */
void
gst_ebml_write_utf8 (GstEbmlWrite * ebml, guint32 id, const gchar * str)
{
gst_ebml_write_ascii (ebml, id, str);
}
-/* date should be in seconds since the unix epoch */
+
+/**
+ * gst_ebml_write_date:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ * @date: Date in seconds since the unix epoch.
+ *
+ * Write date element.
+ */
void
gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date)
{
gst_ebml_write_sint (ebml, id, (date - GST_EBML_DATE_OFFSET) * GST_SECOND);
}
-/*
+/**
+ * gst_ebml_write_master_start:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ *
+ * Start wiriting mater element.
+ *
* Master writing is annoying. We use a size marker of
* the max. allowed length, so that we can later fill it
* in validly.
+ *
+ * Returns: Master starting position.
*/
-
guint64
gst_ebml_write_master_start (GstEbmlWrite * ebml, guint32 id)
{
@@ -453,12 +599,20 @@ gst_ebml_write_master_start (GstEbmlWrite * ebml, guint32 id)
t = GST_BUFFER_SIZE (buf);
gst_ebml_write_element_id (buf, id);
pos += GST_BUFFER_SIZE (buf) - t;
- gst_ebml_write_element_size (buf, -1);
+ gst_ebml_write_element_size (buf, GST_EBML_SIZE_UNKNOWN);
gst_ebml_write_element_push (ebml, buf);
return pos;
}
+
+/**
+ * gst_ebml_write_master_finish:
+ * @ebml: #GstEbmlWrite
+ * @startpos: Master starting position.
+ *
+ * Finish writing master element.
+ */
void
gst_ebml_write_master_finish (GstEbmlWrite * ebml, guint64 startpos)
{
@@ -476,6 +630,16 @@ gst_ebml_write_master_finish (GstEbmlWrite * ebml, guint64 startpos)
gst_ebml_write_seek (ebml, pos);
}
+
+/**
+ * gst_ebml_write_binary:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ * @binary: Data to be written.
+ * @length: Length of the data
+ *
+ * Write an element with binary data.
+ */
void
gst_ebml_write_binary (GstEbmlWrite * ebml,
guint32 id, guint8 * binary, guint64 length)
@@ -488,13 +652,20 @@ gst_ebml_write_binary (GstEbmlWrite * ebml,
gst_ebml_write_element_push (ebml, buf);
}
-/*
+
+/**
+ * gst_ebml_write_buffer_header:
+ * @ebml: #GstEbmlWrite
+ * @id: Element ID.
+ * @length: Length of the data
+ *
+ * Write header of the binary element (use with gst_ebml_write_buffer function).
+ *
* For things like video frames and audio samples,
* you want to use this function, as it doesn't have
* the overhead of memcpy() that other functions
* such as write_binary() do have.
*/
-
void
gst_ebml_write_buffer_header (GstEbmlWrite * ebml, guint32 id, guint64 length)
{
@@ -505,13 +676,29 @@ gst_ebml_write_buffer_header (GstEbmlWrite * ebml, guint32 id, guint64 length)
gst_ebml_write_element_push (ebml, buf);
}
+
+/**
+ * gst_ebml_write_buffer:
+ * @ebml: #GstEbmlWrite
+ * @data: #GstBuffer cointaining the data.
+ *
+ * Write binary element (see gst_ebml_write_buffer_header).
+ */
void
gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * data)
{
gst_ebml_write_element_push (ebml, data);
}
-/*
+
+/**
+ * gst_ebml_replace_uint:
+ * @ebml: #GstEbmlWrite
+ * @pos: Position of the uint that should be replaced.
+ * @num: New value.
+ *
+ * Replace uint with a new value.
+ *
* When replacing a uint, we assume that it is *always*
* 8-byte, since that's the safest guess we can do. This
* is just for simplicity.
@@ -519,7 +706,6 @@ gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * data)
* FIXME: this function needs to be replaced with something
* proper. This is a crude hack.
*/
-
void
gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
{
@@ -533,10 +719,14 @@ gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
gst_ebml_write_seek (ebml, oldpos);
}
-/*
+/**
+ * gst_ebml_write_header:
+ * @ebml: #GstEbmlWrite
+ * @doctype: Document type.
+ * @version: Document type version.
+ *
* Write EBML header.
*/
-
void
gst_ebml_write_header (GstEbmlWrite * ebml, gchar * doctype, guint version)
{