2 * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 * (c) 2005 Michal Benes <michal.benes@xeris.cz>
5 * ebml-write.c: write EBML data to file/stream
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
28 #include <gst/floatcast/floatcast.h>
30 #include "ebml-write.h"
34 GST_DEBUG_CATEGORY_STATIC (gst_ebml_write_debug);
35 #define GST_CAT_DEFAULT gst_ebml_write_debug
37 #define _do_init(thing) \
38 GST_DEBUG_CATEGORY_INIT (gst_ebml_write_debug, "GstEbmlWrite", 0, "Write EBML structured data")
39 GST_BOILERPLATE_FULL (GstEbmlWrite, gst_ebml_write, GstObject, GST_TYPE_OBJECT,
42 static void gst_ebml_write_finalize (GObject * object);
46 gst_ebml_write_base_init (gpointer g_class)
51 gst_ebml_write_class_init (GstEbmlWriteClass * klass)
53 GObjectClass *object = G_OBJECT_CLASS (klass);
55 object->finalize = gst_ebml_write_finalize;
59 gst_ebml_write_init (GstEbmlWrite * ebml, GstEbmlWriteClass * klass)
69 gst_ebml_write_finalize (GObject * object)
71 GstEbmlWrite *ebml = GST_EBML_WRITE (object);
73 gst_object_unref (ebml->srcpad);
76 gst_buffer_unref (ebml->cache);
80 GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
86 * @srcpad: Source pad to which the output will be pushed.
88 * Creates a new #GstEbmlWrite.
90 * Returns: a new #GstEbmlWrite
93 gst_ebml_write_new (GstPad * srcpad)
96 GST_EBML_WRITE (g_object_new (GST_TYPE_EBML_WRITE, NULL));
98 ebml->srcpad = gst_object_ref (srcpad);
99 ebml->timestamp = GST_CLOCK_TIME_NONE;
101 gst_ebml_write_reset (ebml);
108 * gst_ebml_write_reset:
109 * @ebml: a #GstEbmlWrite.
111 * Reset internal state of #GstEbmlWrite.
114 gst_ebml_write_reset (GstEbmlWrite * ebml)
119 gst_buffer_unref (ebml->cache);
122 ebml->cache_size = 0;
123 ebml->last_write_result = GST_FLOW_OK;
124 ebml->timestamp = GST_CLOCK_TIME_NONE;
125 ebml->need_newsegment = TRUE;
130 * gst_ebml_last_write_result:
131 * @ebml: a #GstEbmlWrite.
133 * Returns: GST_FLOW_OK if there was not write error since the last call of
134 * gst_ebml_last_write_result or code of the error.
137 gst_ebml_last_write_result (GstEbmlWrite * ebml)
139 GstFlowReturn res = ebml->last_write_result;
141 ebml->last_write_result = GST_FLOW_OK;
148 * gst_ebml_write_set_cache:
149 * @ebml: a #GstEbmlWrite.
150 * @size: size of the cache.
153 * The idea is that you use this for writing a lot
154 * of small elements. This will just "queue" all of
155 * them and they'll be pushed to the next element all
156 * at once. This saves memory and time for buffer
157 * allocation and init, and it looks better.
160 gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
162 /* FIXME: This is currently broken. I don't know why yet. */
165 g_return_if_fail (ebml->cache == NULL);
167 ebml->cache = gst_buffer_new_and_alloc (size);
168 ebml->cache_size = size;
169 GST_BUFFER_SIZE (ebml->cache) = 0;
170 GST_BUFFER_OFFSET (ebml->cache) = ebml->pos;
175 * gst_ebml_write_flush_cache:
176 * @ebml: a #GstEbmlWrite.
181 gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
186 /* this is very important. It may fail, in which case the client
187 * programmer didn't use the cache somewhere. That's fatal. */
188 g_assert (ebml->handled == GST_BUFFER_SIZE (ebml->cache));
189 g_assert (GST_BUFFER_SIZE (ebml->cache) +
190 GST_BUFFER_OFFSET (ebml->cache) == ebml->pos);
192 if (ebml->last_write_result == GST_FLOW_OK) {
193 if (ebml->need_newsegment) {
196 g_assert (ebml->handled == 0);
197 ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
198 if (gst_pad_push_event (ebml->srcpad, ev))
199 ebml->need_newsegment = FALSE;
201 ebml->last_write_result = gst_pad_push (ebml->srcpad, ebml->cache);
205 ebml->cache_size = 0;
211 * gst_ebml_write_element_new:
212 * @ebml: a #GstEbmlWrite.
213 * @size: size of the requested buffer.
215 * Create a buffer for one element. If there is
216 * a cache, use that instead.
218 * Returns: A new #GstBuffer.
221 gst_ebml_write_element_new (GstEbmlWrite * ebml, guint size)
223 /* Create new buffer of size + ID + length */
231 if (ebml->cache_size - GST_BUFFER_SIZE (ebml->cache) < size) {
232 GST_LOG ("Cache available, but too small. Clearing...");
233 gst_ebml_write_flush_cache (ebml);
239 /* else, use a one-element buffer. This is slower */
240 buf = gst_buffer_new_and_alloc (size);
241 GST_BUFFER_SIZE (buf) = 0;
242 GST_BUFFER_TIMESTAMP (buf) = ebml->timestamp;
249 * gst_ebml_write_element_id:
250 * @buf: Buffer to which id should be written.
251 * @id: Element ID that should be written.
253 * Write element ID into a buffer.
256 gst_ebml_write_element_id (GstBuffer * buf, guint32 id)
258 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
259 guint bytes = 4, mask = 0x10;
262 while (!(id & (mask << ((bytes - 1) * 8))) && bytes > 0) {
267 /* if invalid ID, use dummy */
269 GST_WARNING ("Invalid ID, voiding");
271 id = GST_EBML_ID_VOID;
275 GST_BUFFER_SIZE (buf) += bytes;
277 data[bytes] = id & 0xff;
284 * gst_ebml_write_element_size:
285 * @buf: #GstBuffer to which size should be written.
286 * @size: Element length.
288 * Write element length into a buffer.
291 gst_ebml_write_element_size (GstBuffer * buf, guint64 size)
293 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
294 guint bytes = 1, mask = 0x80;
296 if (size != GST_EBML_SIZE_UNKNOWN) {
297 /* how many bytes? - use mask-1 because an all-1 bitset is not allowed */
298 while ((size >> ((bytes - 1) * 8)) >= (mask - 1) && bytes <= 8) {
303 /* if invalid size, use max. */
305 GST_WARNING ("Invalid size, writing size unknown");
308 /* Now here's a real FIXME: we cannot read those yet! */
309 size = GST_EBML_SIZE_UNKNOWN;
316 /* write out, BE, with length size marker */
317 GST_BUFFER_SIZE (buf) += bytes;
318 while (bytes-- > 0) {
319 data[bytes] = size & 0xff;
328 * gst_ebml_write_element_data:
329 * @buf: #GstBuffer to which data should be written.
330 * @write: Data that should be written.
331 * @length: Length of the data.
333 * Write element data into a buffer.
336 gst_ebml_write_element_data (GstBuffer * buf, guint8 * write, guint64 length)
338 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
340 memcpy (data, write, length);
341 GST_BUFFER_SIZE (buf) += length;
346 * gst_ebml_write_element_push:
347 * @ebml: #GstEbmlWrite
348 * @buf: #GstBuffer to be written.
350 * Write out buffer by moving it to the next element.
353 gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf)
355 guint data_size = GST_BUFFER_SIZE (buf) - ebml->handled;
357 ebml->pos += data_size;
358 if (buf == ebml->cache) {
359 ebml->handled += data_size;
362 /* if there's no cache, then don't push it! */
364 g_assert (buf == ebml->cache);
368 if (ebml->last_write_result == GST_FLOW_OK) {
369 if (ebml->need_newsegment) {
372 g_assert (ebml->handled == 0);
373 ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
374 if (gst_pad_push_event (ebml->srcpad, ev))
375 ebml->need_newsegment = FALSE;
377 buf = gst_buffer_make_metadata_writable (buf);
378 gst_buffer_set_caps (buf, GST_PAD_CAPS (ebml->srcpad));
379 ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
381 if (buf != ebml->cache)
382 gst_buffer_unref (buf);
388 * gst_ebml_write_seek:
389 * @ebml: #GstEbmlWrite
390 * @pos: Seek position.
395 gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
399 /* Cache seeking. A bit dangerous, we assume the client writer
400 * knows what he's doing... */
403 if (pos >= GST_BUFFER_OFFSET (ebml->cache) &&
404 pos < GST_BUFFER_OFFSET (ebml->cache) + ebml->cache_size) {
405 GST_BUFFER_SIZE (ebml->cache) = pos - GST_BUFFER_OFFSET (ebml->cache);
407 ebml->handled -= ebml->pos - pos;
409 ebml->handled += pos - ebml->pos;
412 GST_LOG ("Seek outside cache range. Clearing...");
413 gst_ebml_write_flush_cache (ebml);
417 event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, pos, -1, 0);
418 if (gst_pad_push_event (ebml->srcpad, event)) {
419 GST_DEBUG ("Seek'd to offset %" G_GUINT64_FORMAT, pos);
421 GST_WARNING ("Seek to offset %" G_GUINT64_FORMAT " failed", pos);
428 * gst_ebml_write_get_uint_size:
429 * @num: Number to be encoded.
431 * Get number of bytes needed to write a uint.
433 * Returns: Encoded uint length.
436 gst_ebml_write_get_uint_size (guint64 num)
441 while (num >= (G_GINT64_CONSTANT (1) << (size * 8)) && size < 8) {
450 * gst_ebml_write_set_uint:
451 * @buf: #GstBuffer to which ithe number should be written.
452 * @num: Number to be written.
453 * @size: Encoded number length.
455 * Write an uint into a buffer.
458 gst_ebml_write_set_uint (GstBuffer * buf, guint64 num, guint size)
462 data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
463 GST_BUFFER_SIZE (buf) += size;
465 data[size] = num & 0xff;
472 * gst_ebml_write_uint:
473 * @ebml: #GstEbmlWrite
475 * @num: Number to be written.
477 * Write uint element.
480 gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num)
482 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
483 guint size = gst_ebml_write_get_uint_size (num);
486 gst_ebml_write_element_id (buf, id);
487 gst_ebml_write_element_size (buf, size);
488 gst_ebml_write_set_uint (buf, num, size);
489 gst_ebml_write_element_push (ebml, buf);
494 * gst_ebml_write_sint:
495 * @ebml: #GstEbmlWrite
497 * @num: Number to be written.
499 * Write sint element.
502 gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
504 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
506 /* if the signed number is on the edge of a extra-byte,
507 * then we'll fall over when detecting it. Example: if I
508 * have a number (-)0x8000 (G_MINSHORT), then my abs()<<1
509 * will be 0x10000; this is G_MAXUSHORT+1! So: if (<0) -1. */
510 guint64 unum = (num < 0 ? (-num - 1) << 1 : num << 1);
511 guint size = gst_ebml_write_get_uint_size (unum);
517 unum = 0x80 << (size - 1);
519 unum |= 0x80 << (size - 1);
523 gst_ebml_write_element_id (buf, id);
524 gst_ebml_write_element_size (buf, size);
525 gst_ebml_write_set_uint (buf, unum, size);
526 gst_ebml_write_element_push (ebml, buf);
531 * gst_ebml_write_float:
532 * @ebml: #GstEbmlWrite
534 * @num: Number to be written.
536 * Write float element.
539 gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
541 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
543 gst_ebml_write_element_id (buf, id);
544 gst_ebml_write_element_size (buf, 8);
545 num = GDOUBLE_TO_BE (num);
546 gst_ebml_write_element_data (buf, (guint8 *) & num, 8);
547 gst_ebml_write_element_push (ebml, buf);
552 * gst_ebml_write_ascii:
553 * @ebml: #GstEbmlWrite
555 * @str: String to be written.
557 * Write string element.
560 gst_ebml_write_ascii (GstEbmlWrite * ebml, guint32 id, const gchar * str)
562 gint len = strlen (str) + 1; /* add trailing '\0' */
563 GstBuffer *buf = gst_ebml_write_element_new (ebml, len);
565 gst_ebml_write_element_id (buf, id);
566 gst_ebml_write_element_size (buf, len);
567 gst_ebml_write_element_data (buf, (guint8 *) str, len);
568 gst_ebml_write_element_push (ebml, buf);
573 * gst_ebml_write_utf8:
574 * @ebml: #GstEbmlWrite
576 * @str: String to be written.
578 * Write utf8 encoded string element.
581 gst_ebml_write_utf8 (GstEbmlWrite * ebml, guint32 id, const gchar * str)
583 gst_ebml_write_ascii (ebml, id, str);
588 * gst_ebml_write_date:
589 * @ebml: #GstEbmlWrite
591 * @date: Date in seconds since the unix epoch.
593 * Write date element.
596 gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date)
598 gst_ebml_write_sint (ebml, id, (date - GST_EBML_DATE_OFFSET) * GST_SECOND);
602 * gst_ebml_write_master_start:
603 * @ebml: #GstEbmlWrite
606 * Start wiriting mater element.
608 * Master writing is annoying. We use a size marker of
609 * the max. allowed length, so that we can later fill it
612 * Returns: Master starting position.
615 gst_ebml_write_master_start (GstEbmlWrite * ebml, guint32 id)
617 guint64 pos = ebml->pos, t;
618 GstBuffer *buf = gst_ebml_write_element_new (ebml, 0);
620 t = GST_BUFFER_SIZE (buf);
621 gst_ebml_write_element_id (buf, id);
622 pos += GST_BUFFER_SIZE (buf) - t;
623 gst_ebml_write_element_size (buf, GST_EBML_SIZE_UNKNOWN);
624 gst_ebml_write_element_push (ebml, buf);
631 * gst_ebml_write_master_finish:
632 * @ebml: #GstEbmlWrite
633 * @startpos: Master starting position.
635 * Finish writing master element.
638 gst_ebml_write_master_finish (GstEbmlWrite * ebml, guint64 startpos)
640 guint64 pos = ebml->pos;
643 gst_ebml_write_seek (ebml, startpos);
644 buf = gst_ebml_write_element_new (ebml, 0);
646 GUINT64_TO_BE ((G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8));
647 memcpy (GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf), (guint8 *) & startpos,
649 GST_BUFFER_SIZE (buf) += 8;
650 gst_ebml_write_element_push (ebml, buf);
651 gst_ebml_write_seek (ebml, pos);
656 * gst_ebml_write_binary:
657 * @ebml: #GstEbmlWrite
659 * @binary: Data to be written.
660 * @length: Length of the data
662 * Write an element with binary data.
665 gst_ebml_write_binary (GstEbmlWrite * ebml,
666 guint32 id, guint8 * binary, guint64 length)
668 GstBuffer *buf = gst_ebml_write_element_new (ebml, length);
670 gst_ebml_write_element_id (buf, id);
671 gst_ebml_write_element_size (buf, length);
672 gst_ebml_write_element_data (buf, binary, length);
673 gst_ebml_write_element_push (ebml, buf);
678 * gst_ebml_write_buffer_header:
679 * @ebml: #GstEbmlWrite
681 * @length: Length of the data
683 * Write header of the binary element (use with gst_ebml_write_buffer function).
685 * For things like video frames and audio samples,
686 * you want to use this function, as it doesn't have
687 * the overhead of memcpy() that other functions
688 * such as write_binary() do have.
691 gst_ebml_write_buffer_header (GstEbmlWrite * ebml, guint32 id, guint64 length)
693 GstBuffer *buf = gst_ebml_write_element_new (ebml, 0);
695 gst_ebml_write_element_id (buf, id);
696 gst_ebml_write_element_size (buf, length);
697 gst_ebml_write_element_push (ebml, buf);
702 * gst_ebml_write_buffer:
703 * @ebml: #GstEbmlWrite
704 * @data: #GstBuffer cointaining the data.
706 * Write binary element (see gst_ebml_write_buffer_header).
709 gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * data)
711 gst_ebml_write_element_push (ebml, data);
716 * gst_ebml_replace_uint:
717 * @ebml: #GstEbmlWrite
718 * @pos: Position of the uint that should be replaced.
721 * Replace uint with a new value.
723 * When replacing a uint, we assume that it is *always*
724 * 8-byte, since that's the safest guess we can do. This
725 * is just for simplicity.
727 * FIXME: this function needs to be replaced with something
728 * proper. This is a crude hack.
731 gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
733 guint64 oldpos = ebml->pos;
734 GstBuffer *buf = gst_buffer_new_and_alloc (8);
736 gst_ebml_write_seek (ebml, pos);
737 GST_BUFFER_SIZE (buf) = 0;
738 gst_ebml_write_set_uint (buf, num, 8);
739 gst_ebml_write_element_push (ebml, buf);
740 gst_ebml_write_seek (ebml, oldpos);
744 * gst_ebml_write_header:
745 * @ebml: #GstEbmlWrite
746 * @doctype: Document type.
747 * @version: Document type version.
752 gst_ebml_write_header (GstEbmlWrite * ebml, gchar * doctype, guint version)
756 /* write the basic EBML header */
757 gst_ebml_write_set_cache (ebml, 0x40);
758 pos = gst_ebml_write_master_start (ebml, GST_EBML_ID_HEADER);
759 #if (GST_EBML_VERSION != 1)
760 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLVERSION, GST_EBML_VERSION);
761 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLREADVERSION, GST_EBML_VERSION);
764 /* we don't write these until they're "non-default" (never!) */
765 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXIDLENGTH, sizeof (guint32));
766 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXSIZELENGTH, sizeof (guint64));
768 gst_ebml_write_ascii (ebml, GST_EBML_ID_DOCTYPE, doctype);
769 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEVERSION, version);
770 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
771 gst_ebml_write_master_finish (ebml, pos);
772 gst_ebml_write_flush_cache (ebml);