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, "ebmlwrite", 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)
65 ebml->streamheader = NULL;
66 ebml->streamheader_pos = 0;
67 ebml->writing_streamheader = FALSE;
71 gst_ebml_write_finalize (GObject * object)
73 GstEbmlWrite *ebml = GST_EBML_WRITE (object);
75 gst_object_unref (ebml->srcpad);
78 gst_byte_writer_free (ebml->cache);
82 if (ebml->streamheader) {
83 gst_byte_writer_free (ebml->streamheader);
84 ebml->streamheader = NULL;
87 GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
93 * @srcpad: Source pad to which the output will be pushed.
95 * Creates a new #GstEbmlWrite.
97 * Returns: a new #GstEbmlWrite
100 gst_ebml_write_new (GstPad * srcpad)
103 GST_EBML_WRITE (g_object_new (GST_TYPE_EBML_WRITE, NULL));
105 ebml->srcpad = gst_object_ref (srcpad);
106 ebml->timestamp = GST_CLOCK_TIME_NONE;
108 gst_ebml_write_reset (ebml);
115 * gst_ebml_write_reset:
116 * @ebml: a #GstEbmlWrite.
118 * Reset internal state of #GstEbmlWrite.
121 gst_ebml_write_reset (GstEbmlWrite * ebml)
126 gst_byte_writer_free (ebml->cache);
129 ebml->last_write_result = GST_FLOW_OK;
130 ebml->timestamp = GST_CLOCK_TIME_NONE;
131 ebml->need_newsegment = TRUE;
136 * gst_ebml_last_write_result:
137 * @ebml: a #GstEbmlWrite.
139 * Returns: GST_FLOW_OK if there was not write error since the last call of
140 * gst_ebml_last_write_result or code of the error.
143 gst_ebml_last_write_result (GstEbmlWrite * ebml)
145 GstFlowReturn res = ebml->last_write_result;
147 ebml->last_write_result = GST_FLOW_OK;
154 gst_ebml_start_streamheader (GstEbmlWrite * ebml)
156 g_return_if_fail (ebml->streamheader == NULL);
158 GST_DEBUG ("Starting streamheader at %" G_GUINT64_FORMAT, ebml->pos);
159 ebml->streamheader = gst_byte_writer_new_with_size (1000, FALSE);
160 ebml->streamheader_pos = ebml->pos;
161 ebml->writing_streamheader = TRUE;
165 gst_ebml_stop_streamheader (GstEbmlWrite * ebml)
169 if (!ebml->streamheader)
172 buffer = gst_byte_writer_free_and_get_buffer (ebml->streamheader);
173 ebml->streamheader = NULL;
174 GST_DEBUG ("Streamheader was size %d", GST_BUFFER_SIZE (buffer));
176 ebml->writing_streamheader = FALSE;
181 * gst_ebml_write_set_cache:
182 * @ebml: a #GstEbmlWrite.
183 * @size: size of the cache.
186 * The idea is that you use this for writing a lot
187 * of small elements. This will just "queue" all of
188 * them and they'll be pushed to the next element all
189 * at once. This saves memory and time for buffer
190 * allocation and init, and it looks better.
193 gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
195 g_return_if_fail (ebml->cache == NULL);
197 GST_DEBUG ("Starting cache at %" G_GUINT64_FORMAT, ebml->pos);
198 ebml->cache = gst_byte_writer_new_with_size (size, FALSE);
199 ebml->cache_pos = ebml->pos;
203 * gst_ebml_write_flush_cache:
204 * @ebml: a #GstEbmlWrite.
209 gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
216 buffer = gst_byte_writer_free_and_get_buffer (ebml->cache);
218 GST_DEBUG ("Flushing cache of size %d", GST_BUFFER_SIZE (buffer));
220 if (ebml->last_write_result == GST_FLOW_OK) {
221 if (ebml->need_newsegment) {
224 ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
225 if (gst_pad_push_event (ebml->srcpad, ev))
226 ebml->need_newsegment = FALSE;
228 ebml->last_write_result = gst_pad_push (ebml->srcpad, buffer);
230 gst_buffer_unref (buffer);
236 * gst_ebml_write_element_new:
237 * @ebml: a #GstEbmlWrite.
238 * @size: size of the requested buffer.
240 * Create a buffer for one element. If there is
241 * a cache, use that instead.
243 * Returns: A new #GstBuffer.
246 gst_ebml_write_element_new (GstEbmlWrite * ebml, guint size)
248 /* Create new buffer of size + ID + length */
254 buf = gst_buffer_new_and_alloc (size);
255 GST_BUFFER_SIZE (buf) = 0;
256 GST_BUFFER_TIMESTAMP (buf) = ebml->timestamp;
263 * gst_ebml_write_element_id:
264 * @buf: Buffer to which id should be written.
265 * @id: Element ID that should be written.
267 * Write element ID into a buffer.
270 gst_ebml_write_element_id (GstBuffer * buf, guint32 id)
272 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
273 guint bytes = 4, mask = 0x10;
276 while (!(id & (mask << ((bytes - 1) * 8))) && bytes > 0) {
281 /* if invalid ID, use dummy */
283 GST_WARNING ("Invalid ID, voiding");
285 id = GST_EBML_ID_VOID;
289 GST_BUFFER_SIZE (buf) += bytes;
291 data[bytes] = id & 0xff;
298 * gst_ebml_write_element_size:
299 * @buf: #GstBuffer to which size should be written.
300 * @size: Element length.
302 * Write element length into a buffer.
305 gst_ebml_write_element_size (GstBuffer * buf, guint64 size)
307 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
308 guint bytes = 1, mask = 0x80;
310 if (size != GST_EBML_SIZE_UNKNOWN) {
311 /* how many bytes? - use mask-1 because an all-1 bitset is not allowed */
312 while ((size >> ((bytes - 1) * 8)) >= (mask - 1) && bytes <= 8) {
317 /* if invalid size, use max. */
319 GST_WARNING ("Invalid size, writing size unknown");
322 /* Now here's a real FIXME: we cannot read those yet! */
323 size = GST_EBML_SIZE_UNKNOWN;
330 /* write out, BE, with length size marker */
331 GST_BUFFER_SIZE (buf) += bytes;
332 while (bytes-- > 0) {
333 data[bytes] = size & 0xff;
342 * gst_ebml_write_element_data:
343 * @buf: #GstBuffer to which data should be written.
344 * @write: Data that should be written.
345 * @length: Length of the data.
347 * Write element data into a buffer.
350 gst_ebml_write_element_data (GstBuffer * buf, guint8 * write, guint64 length)
352 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
354 memcpy (data, write, length);
355 GST_BUFFER_SIZE (buf) += length;
360 * gst_ebml_write_element_push:
361 * @ebml: #GstEbmlWrite
362 * @buf: #GstBuffer to be written.
364 * Write out buffer by moving it to the next element.
367 gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf)
369 guint data_size = GST_BUFFER_SIZE (buf);
371 ebml->pos += data_size;
373 /* if there's no cache, then don't push it! */
374 if (ebml->writing_streamheader) {
375 gst_byte_writer_put_data (ebml->streamheader, GST_BUFFER_DATA (buf),
379 gst_byte_writer_put_data (ebml->cache, GST_BUFFER_DATA (buf), data_size);
380 gst_buffer_unref (buf);
384 if (ebml->last_write_result == GST_FLOW_OK) {
385 if (ebml->need_newsegment) {
388 ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
389 if (gst_pad_push_event (ebml->srcpad, ev))
390 ebml->need_newsegment = FALSE;
392 buf = gst_buffer_make_metadata_writable (buf);
393 gst_buffer_set_caps (buf, GST_PAD_CAPS (ebml->srcpad));
394 ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
396 gst_buffer_unref (buf);
402 * gst_ebml_write_seek:
403 * @ebml: #GstEbmlWrite
404 * @pos: Seek position.
409 gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
413 if (ebml->writing_streamheader) {
414 GST_DEBUG ("wanting to seek to pos %" G_GUINT64_FORMAT, pos);
415 if (pos >= ebml->streamheader_pos &&
416 pos <= ebml->streamheader_pos + ebml->streamheader->parent.size) {
417 gst_byte_writer_set_pos (ebml->streamheader,
418 pos - ebml->streamheader_pos);
419 GST_DEBUG ("seeked in streamheader to position %" G_GUINT64_FORMAT,
420 pos - ebml->streamheader_pos);
423 ("we are writing streamheader still and seek is out of bounds");
426 /* Cache seeking. A bit dangerous, we assume the client writer
427 * knows what he's doing... */
430 if (pos >= ebml->cache_pos &&
431 pos <= ebml->cache_pos + ebml->cache->parent.size) {
433 gst_byte_writer_set_pos (ebml->cache, ebml->pos - ebml->cache_pos);
436 GST_LOG ("Seek outside cache range. Clearing...");
437 gst_ebml_write_flush_cache (ebml);
441 event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, pos, -1, 0);
442 if (gst_pad_push_event (ebml->srcpad, event)) {
443 GST_DEBUG ("Seek'd to offset %" G_GUINT64_FORMAT, pos);
445 GST_WARNING ("Seek to offset %" G_GUINT64_FORMAT " failed", pos);
452 * gst_ebml_write_get_uint_size:
453 * @num: Number to be encoded.
455 * Get number of bytes needed to write a uint.
457 * Returns: Encoded uint length.
460 gst_ebml_write_get_uint_size (guint64 num)
465 while (num >= (G_GINT64_CONSTANT (1) << (size * 8)) && size < 8) {
474 * gst_ebml_write_set_uint:
475 * @buf: #GstBuffer to which ithe number should be written.
476 * @num: Number to be written.
477 * @size: Encoded number length.
479 * Write an uint into a buffer.
482 gst_ebml_write_set_uint (GstBuffer * buf, guint64 num, guint size)
486 data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
487 GST_BUFFER_SIZE (buf) += size;
489 data[size] = num & 0xff;
496 * gst_ebml_write_uint:
497 * @ebml: #GstEbmlWrite
499 * @num: Number to be written.
501 * Write uint element.
504 gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num)
506 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
507 guint size = gst_ebml_write_get_uint_size (num);
510 gst_ebml_write_element_id (buf, id);
511 gst_ebml_write_element_size (buf, size);
512 gst_ebml_write_set_uint (buf, num, size);
513 gst_ebml_write_element_push (ebml, buf);
518 * gst_ebml_write_sint:
519 * @ebml: #GstEbmlWrite
521 * @num: Number to be written.
523 * Write sint element.
526 gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
528 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
530 /* if the signed number is on the edge of a extra-byte,
531 * then we'll fall over when detecting it. Example: if I
532 * have a number (-)0x8000 (G_MINSHORT), then my abs()<<1
533 * will be 0x10000; this is G_MAXUSHORT+1! So: if (<0) -1. */
534 guint64 unum = (num < 0 ? (-num - 1) << 1 : num << 1);
535 guint size = gst_ebml_write_get_uint_size (unum);
541 unum = 0x80 << (size - 1);
543 unum |= 0x80 << (size - 1);
547 gst_ebml_write_element_id (buf, id);
548 gst_ebml_write_element_size (buf, size);
549 gst_ebml_write_set_uint (buf, unum, size);
550 gst_ebml_write_element_push (ebml, buf);
555 * gst_ebml_write_float:
556 * @ebml: #GstEbmlWrite
558 * @num: Number to be written.
560 * Write float element.
563 gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
565 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
567 gst_ebml_write_element_id (buf, id);
568 gst_ebml_write_element_size (buf, 8);
569 num = GDOUBLE_TO_BE (num);
570 gst_ebml_write_element_data (buf, (guint8 *) & num, 8);
571 gst_ebml_write_element_push (ebml, buf);
576 * gst_ebml_write_ascii:
577 * @ebml: #GstEbmlWrite
579 * @str: String to be written.
581 * Write string element.
584 gst_ebml_write_ascii (GstEbmlWrite * ebml, guint32 id, const gchar * str)
586 gint len = strlen (str) + 1; /* add trailing '\0' */
587 GstBuffer *buf = gst_ebml_write_element_new (ebml, len);
589 gst_ebml_write_element_id (buf, id);
590 gst_ebml_write_element_size (buf, len);
591 gst_ebml_write_element_data (buf, (guint8 *) str, len);
592 gst_ebml_write_element_push (ebml, buf);
597 * gst_ebml_write_utf8:
598 * @ebml: #GstEbmlWrite
600 * @str: String to be written.
602 * Write utf8 encoded string element.
605 gst_ebml_write_utf8 (GstEbmlWrite * ebml, guint32 id, const gchar * str)
607 gst_ebml_write_ascii (ebml, id, str);
612 * gst_ebml_write_date:
613 * @ebml: #GstEbmlWrite
615 * @date: Date in seconds since the unix epoch.
617 * Write date element.
620 gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date)
622 gst_ebml_write_sint (ebml, id, (date - GST_EBML_DATE_OFFSET) * GST_SECOND);
626 * gst_ebml_write_master_start:
627 * @ebml: #GstEbmlWrite
630 * Start wiriting mater element.
632 * Master writing is annoying. We use a size marker of
633 * the max. allowed length, so that we can later fill it
636 * Returns: Master starting position.
639 gst_ebml_write_master_start (GstEbmlWrite * ebml, guint32 id)
641 guint64 pos = ebml->pos, t;
642 GstBuffer *buf = gst_ebml_write_element_new (ebml, 0);
644 t = GST_BUFFER_SIZE (buf);
645 gst_ebml_write_element_id (buf, id);
646 pos += GST_BUFFER_SIZE (buf) - t;
647 gst_ebml_write_element_size (buf, GST_EBML_SIZE_UNKNOWN);
648 gst_ebml_write_element_push (ebml, buf);
655 * gst_ebml_write_master_finish_full:
656 * @ebml: #GstEbmlWrite
657 * @startpos: Master starting position.
659 * Finish writing master element. Size of master element is difference between
660 * current position and the element start, and @extra_size added to this.
663 gst_ebml_write_master_finish_full (GstEbmlWrite * ebml, guint64 startpos,
666 guint64 pos = ebml->pos;
669 gst_ebml_write_seek (ebml, startpos);
670 buf = gst_buffer_new_and_alloc (8);
671 GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf),
672 (G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8 + extra_size));
673 gst_ebml_write_element_push (ebml, buf);
674 gst_ebml_write_seek (ebml, pos);
678 gst_ebml_write_master_finish (GstEbmlWrite * ebml, guint64 startpos)
680 gst_ebml_write_master_finish_full (ebml, startpos, 0);
684 * gst_ebml_write_binary:
685 * @ebml: #GstEbmlWrite
687 * @binary: Data to be written.
688 * @length: Length of the data
690 * Write an element with binary data.
693 gst_ebml_write_binary (GstEbmlWrite * ebml,
694 guint32 id, guint8 * binary, guint64 length)
696 GstBuffer *buf = gst_ebml_write_element_new (ebml, length);
698 gst_ebml_write_element_id (buf, id);
699 gst_ebml_write_element_size (buf, length);
700 gst_ebml_write_element_data (buf, binary, length);
701 gst_ebml_write_element_push (ebml, buf);
706 * gst_ebml_write_buffer_header:
707 * @ebml: #GstEbmlWrite
709 * @length: Length of the data
711 * Write header of the binary element (use with gst_ebml_write_buffer function).
713 * For things like video frames and audio samples,
714 * you want to use this function, as it doesn't have
715 * the overhead of memcpy() that other functions
716 * such as write_binary() do have.
719 gst_ebml_write_buffer_header (GstEbmlWrite * ebml, guint32 id, guint64 length)
721 GstBuffer *buf = gst_ebml_write_element_new (ebml, 0);
723 gst_ebml_write_element_id (buf, id);
724 gst_ebml_write_element_size (buf, length);
725 gst_ebml_write_element_push (ebml, buf);
730 * gst_ebml_write_buffer:
731 * @ebml: #GstEbmlWrite
732 * @data: #GstBuffer cointaining the data.
734 * Write binary element (see gst_ebml_write_buffer_header).
737 gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * data)
739 gst_ebml_write_element_push (ebml, data);
744 * gst_ebml_replace_uint:
745 * @ebml: #GstEbmlWrite
746 * @pos: Position of the uint that should be replaced.
749 * Replace uint with a new value.
751 * When replacing a uint, we assume that it is *always*
752 * 8-byte, since that's the safest guess we can do. This
753 * is just for simplicity.
755 * FIXME: this function needs to be replaced with something
756 * proper. This is a crude hack.
759 gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
761 guint64 oldpos = ebml->pos;
762 GstBuffer *buf = gst_buffer_new_and_alloc (8);
764 gst_ebml_write_seek (ebml, pos);
765 GST_BUFFER_SIZE (buf) = 0;
766 gst_ebml_write_set_uint (buf, num, 8);
767 gst_ebml_write_element_push (ebml, buf);
768 gst_ebml_write_seek (ebml, oldpos);
772 * gst_ebml_write_header:
773 * @ebml: #GstEbmlWrite
774 * @doctype: Document type.
775 * @version: Document type version.
780 gst_ebml_write_header (GstEbmlWrite * ebml, const gchar * doctype,
785 /* write the basic EBML header */
786 gst_ebml_write_set_cache (ebml, 0x40);
787 pos = gst_ebml_write_master_start (ebml, GST_EBML_ID_HEADER);
788 #if (GST_EBML_VERSION != 1)
789 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLVERSION, GST_EBML_VERSION);
790 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLREADVERSION, GST_EBML_VERSION);
793 /* we don't write these until they're "non-default" (never!) */
794 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXIDLENGTH, sizeof (guint32));
795 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXSIZELENGTH, sizeof (guint64));
797 gst_ebml_write_ascii (ebml, GST_EBML_ID_DOCTYPE, doctype);
798 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEVERSION, version);
799 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
800 gst_ebml_write_master_finish (ebml, pos);
801 gst_ebml_write_flush_cache (ebml);