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., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
29 #include "ebml-write.h"
33 GST_DEBUG_CATEGORY_STATIC (gst_ebml_write_debug);
34 #define GST_CAT_DEFAULT gst_ebml_write_debug
37 GST_DEBUG_CATEGORY_INIT (gst_ebml_write_debug, "ebmlwrite", 0, "Write EBML structured data")
38 #define parent_class gst_ebml_write_parent_class
39 G_DEFINE_TYPE_WITH_CODE (GstEbmlWrite, gst_ebml_write, GST_TYPE_OBJECT,
42 static void gst_ebml_write_finalize (GObject * object);
45 gst_ebml_write_class_init (GstEbmlWriteClass * klass)
47 GObjectClass *object = G_OBJECT_CLASS (klass);
49 object->finalize = gst_ebml_write_finalize;
53 gst_ebml_write_init (GstEbmlWrite * ebml)
57 ebml->last_pos = G_MAXUINT64; /* force segment event */
60 ebml->streamheader = NULL;
61 ebml->streamheader_pos = 0;
62 ebml->writing_streamheader = FALSE;
67 gst_ebml_write_finalize (GObject * object)
69 GstEbmlWrite *ebml = GST_EBML_WRITE (object);
71 gst_object_unref (ebml->srcpad);
74 gst_byte_writer_free (ebml->cache);
78 if (ebml->streamheader) {
79 gst_byte_writer_free (ebml->streamheader);
80 ebml->streamheader = NULL;
84 gst_caps_unref (ebml->caps);
88 G_OBJECT_CLASS (parent_class)->finalize (object);
94 * @srcpad: Source pad to which the output will be pushed.
96 * Creates a new #GstEbmlWrite.
98 * Returns: a new #GstEbmlWrite
101 gst_ebml_write_new (GstPad * srcpad)
104 GST_EBML_WRITE (g_object_new (GST_TYPE_EBML_WRITE, NULL));
106 ebml->srcpad = gst_object_ref (srcpad);
107 ebml->timestamp = GST_CLOCK_TIME_NONE;
109 gst_ebml_write_reset (ebml);
116 * gst_ebml_write_reset:
117 * @ebml: a #GstEbmlWrite.
119 * Reset internal state of #GstEbmlWrite.
122 gst_ebml_write_reset (GstEbmlWrite * ebml)
125 ebml->last_pos = G_MAXUINT64; /* force segment event */
128 gst_byte_writer_free (ebml->cache);
133 gst_caps_unref (ebml->caps);
137 ebml->last_write_result = GST_FLOW_OK;
138 ebml->timestamp = GST_CLOCK_TIME_NONE;
143 * gst_ebml_last_write_result:
144 * @ebml: a #GstEbmlWrite.
146 * Returns: GST_FLOW_OK if there was not write error since the last call of
147 * gst_ebml_last_write_result or code of the error.
150 gst_ebml_last_write_result (GstEbmlWrite * ebml)
152 GstFlowReturn res = ebml->last_write_result;
154 ebml->last_write_result = GST_FLOW_OK;
161 gst_ebml_start_streamheader (GstEbmlWrite * ebml)
163 g_return_if_fail (ebml->streamheader == NULL);
165 GST_DEBUG ("Starting streamheader at %" G_GUINT64_FORMAT, ebml->pos);
166 ebml->streamheader = gst_byte_writer_new_with_size (1000, FALSE);
167 ebml->streamheader_pos = ebml->pos;
168 ebml->writing_streamheader = TRUE;
172 gst_ebml_stop_streamheader (GstEbmlWrite * ebml)
176 if (!ebml->streamheader)
179 buffer = gst_byte_writer_free_and_get_buffer (ebml->streamheader);
180 ebml->streamheader = NULL;
181 GST_DEBUG ("Streamheader was size %" G_GSIZE_FORMAT,
182 gst_buffer_get_size (buffer));
184 ebml->writing_streamheader = FALSE;
189 * gst_ebml_write_set_cache:
190 * @ebml: a #GstEbmlWrite.
191 * @size: size of the cache.
194 * The idea is that you use this for writing a lot
195 * of small elements. This will just "queue" all of
196 * them and they'll be pushed to the next element all
197 * at once. This saves memory and time for buffer
198 * allocation and init, and it looks better.
201 gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
203 g_return_if_fail (ebml->cache == NULL);
205 GST_DEBUG ("Starting cache at %" G_GUINT64_FORMAT, ebml->pos);
206 ebml->cache = gst_byte_writer_new_with_size (size, FALSE);
207 ebml->cache_pos = ebml->pos;
211 gst_ebml_writer_send_segment_event (GstEbmlWrite * ebml, guint64 new_pos)
216 GST_INFO ("seeking to %" G_GUINT64_FORMAT, new_pos);
218 gst_segment_init (&segment, GST_FORMAT_BYTES);
219 segment.start = new_pos;
221 segment.position = 0;
223 res = gst_pad_push_event (ebml->srcpad, gst_event_new_segment (&segment));
226 GST_WARNING ("seek to %" G_GUINT64_FORMAT "failed", new_pos);
232 * gst_ebml_write_flush_cache:
233 * @ebml: a #GstEbmlWrite.
234 * @timestamp: timestamp of the buffer.
239 gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe,
240 GstClockTime timestamp)
247 buffer = gst_byte_writer_free_and_get_buffer (ebml->cache);
249 GST_DEBUG ("Flushing cache of size %" G_GSIZE_FORMAT,
250 gst_buffer_get_size (buffer));
251 GST_BUFFER_TIMESTAMP (buffer) = timestamp;
252 GST_BUFFER_OFFSET (buffer) = ebml->pos - gst_buffer_get_size (buffer);
253 GST_BUFFER_OFFSET_END (buffer) = ebml->pos;
254 if (ebml->last_write_result == GST_FLOW_OK) {
255 if (GST_BUFFER_OFFSET (buffer) != ebml->last_pos) {
256 gst_ebml_writer_send_segment_event (ebml, GST_BUFFER_OFFSET (buffer));
257 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
259 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT);
261 if (ebml->writing_streamheader) {
262 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
264 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_HEADER);
267 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
269 ebml->last_pos = ebml->pos;
270 ebml->last_write_result = gst_pad_push (ebml->srcpad, buffer);
272 gst_buffer_unref (buffer);
278 * gst_ebml_write_element_new:
279 * @ebml: a #GstEbmlWrite.
280 * @size: size of the requested buffer.
282 * Create a buffer for one element. If there is
283 * a cache, use that instead.
285 * Returns: A new #GstBuffer.
288 gst_ebml_write_element_new (GstEbmlWrite * ebml, GstMapInfo * map, guint size)
290 /* Create new buffer of size + ID + length */
296 buf = gst_buffer_new_and_alloc (size);
297 GST_BUFFER_TIMESTAMP (buf) = ebml->timestamp;
299 /* FIXME unmap not possible */
300 gst_buffer_map (buf, map, GST_MAP_WRITE);
307 * gst_ebml_write_element_id:
308 * @data_inout: Pointer to data pointer
309 * @id: Element ID that should be written.
311 * Write element ID into a buffer.
314 gst_ebml_write_element_id (guint8 ** data_inout, guint32 id)
316 guint8 *data = *data_inout;
317 guint bytes = 4, mask = 0x10;
320 while (!(id & (mask << ((bytes - 1) * 8))) && bytes > 0) {
325 /* if invalid ID, use dummy */
327 GST_WARNING ("Invalid ID, voiding");
329 id = GST_EBML_ID_VOID;
333 *data_inout += bytes;
335 data[bytes] = id & 0xff;
342 * gst_ebml_write_element_size:
343 * @data_inout: Pointer to data pointer
344 * @size: Element length.
346 * Write element length into a buffer.
349 gst_ebml_write_element_size (guint8 ** data_inout, guint64 size)
351 guint8 *data = *data_inout;
352 guint bytes = 1, mask = 0x80;
354 if (size != GST_EBML_SIZE_UNKNOWN) {
355 /* how many bytes? - use mask-1 because an all-1 bitset is not allowed */
356 while (bytes <= 8 && (size >> ((bytes - 1) * 8)) >= (mask - 1)) {
361 /* if invalid size, use max. */
363 GST_WARNING ("Invalid size, writing size unknown");
366 /* Now here's a real FIXME: we cannot read those yet! */
367 size = GST_EBML_SIZE_UNKNOWN;
374 /* write out, BE, with length size marker */
375 *data_inout += bytes;
376 while (bytes-- > 0) {
377 data[bytes] = size & 0xff;
386 * gst_ebml_write_element_data:
387 * @data_inout: Pointer to data pointer
388 * @write: Data that should be written.
389 * @length: Length of the data.
391 * Write element data into a buffer.
394 gst_ebml_write_element_data (guint8 ** data_inout, guint8 * write,
397 memcpy (*data_inout, write, length);
398 *data_inout += length;
403 * gst_ebml_write_element_push:
404 * @ebml: #GstEbmlWrite
405 * @buf: #GstBuffer to be written.
406 * @buf_data: Start of data to push from @buf (or NULL for whole buffer).
407 * @buf_data_end: Data pointer positioned after the last byte in @buf_data (or
408 * NULL for whole buffer).
410 * Write out buffer by moving it to the next element.
413 gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf,
414 guint8 * buf_data, guint8 * buf_data_end)
422 data_size = buf_data_end - buf_data;
424 data_size = gst_buffer_get_size (buf);
426 ebml->pos += data_size;
428 /* if there's no cache, then don't push it! */
429 if (ebml->writing_streamheader) {
431 gst_buffer_map (buf, &map, GST_MAP_READ);
435 GST_WARNING ("Failed to map buffer");
436 else if (!gst_byte_writer_put_data (ebml->streamheader, buf_data,
438 GST_WARNING ("Error writing data to streamheader");
442 gst_buffer_map (buf, &map, GST_MAP_READ);
446 GST_WARNING ("Failed to map buffer");
447 else if (!gst_byte_writer_put_data (ebml->cache, buf_data, data_size))
448 GST_WARNING ("Error writing data to cache");
450 gst_buffer_unmap (buf, &map);
451 gst_buffer_unref (buf);
455 if (buf_data && map.data)
456 gst_buffer_unmap (buf, &map);
458 if (ebml->last_write_result == GST_FLOW_OK) {
459 buf = gst_buffer_make_writable (buf);
460 GST_BUFFER_OFFSET (buf) = ebml->pos - data_size;
461 GST_BUFFER_OFFSET_END (buf) = ebml->pos;
462 if (ebml->writing_streamheader) {
463 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
465 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_HEADER);
467 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
469 if (GST_BUFFER_OFFSET (buf) != ebml->last_pos) {
470 gst_ebml_writer_send_segment_event (ebml, GST_BUFFER_OFFSET (buf));
471 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
473 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
475 ebml->last_pos = ebml->pos;
476 ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
478 gst_buffer_unref (buf);
484 * gst_ebml_write_seek:
485 * @ebml: #GstEbmlWrite
486 * @pos: Seek position.
491 gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
493 if (ebml->writing_streamheader) {
494 GST_DEBUG ("wanting to seek to pos %" G_GUINT64_FORMAT, pos);
495 if (pos >= ebml->streamheader_pos &&
496 pos <= ebml->streamheader_pos + ebml->streamheader->parent.size) {
497 gst_byte_writer_set_pos (ebml->streamheader,
498 pos - ebml->streamheader_pos);
499 GST_DEBUG ("seeked in streamheader to position %" G_GUINT64_FORMAT,
500 pos - ebml->streamheader_pos);
503 ("we are writing streamheader still and seek is out of bounds");
506 /* Cache seeking. A bit dangerous, we assume the client writer
507 * knows what he's doing... */
510 if (pos >= ebml->cache_pos &&
511 pos <= ebml->cache_pos + ebml->cache->parent.size) {
512 GST_DEBUG ("seeking in cache to %" G_GUINT64_FORMAT, pos);
514 gst_byte_writer_set_pos (ebml->cache, ebml->pos - ebml->cache_pos);
517 GST_LOG ("Seek outside cache range. Clearing...");
518 gst_ebml_write_flush_cache (ebml, FALSE, GST_CLOCK_TIME_NONE);
522 GST_INFO ("scheduling seek to %" G_GUINT64_FORMAT, pos);
528 * gst_ebml_write_get_uint_size:
529 * @num: Number to be encoded.
531 * Get number of bytes needed to write a uint.
533 * Returns: Encoded uint length.
536 gst_ebml_write_get_uint_size (guint64 num)
541 while (size < 8 && num >= (G_GINT64_CONSTANT (1) << (size * 8))) {
550 * gst_ebml_write_set_uint:
551 * @data_inout: Pointer to data pointer
552 * @num: Number to be written.
553 * @size: Encoded number length.
555 * Write an uint into a buffer.
558 gst_ebml_write_set_uint (guint8 ** data_inout, guint64 num, guint size)
560 guint8 *data = *data_inout;
565 data[size] = num & 0xff;
572 * gst_ebml_write_uint:
573 * @ebml: #GstEbmlWrite
575 * @num: Number to be written.
577 * Write uint element.
580 gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num)
583 guint8 *data_start, *data_end;
584 guint size = gst_ebml_write_get_uint_size (num);
587 buf = gst_ebml_write_element_new (ebml, &map, sizeof (num));
588 data_end = data_start = map.data;
591 gst_ebml_write_element_id (&data_end, id);
592 gst_ebml_write_element_size (&data_end, size);
593 gst_ebml_write_set_uint (&data_end, num, size);
594 gst_buffer_unmap (buf, &map);
595 gst_buffer_set_size (buf, (data_end - data_start));
597 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
602 * gst_ebml_write_sint:
603 * @ebml: #GstEbmlWrite
605 * @num: Number to be written.
607 * Write sint element.
610 gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
613 guint8 *data_start, *data_end;
616 /* if the signed number is on the edge of a extra-byte,
617 * then we'll fall over when detecting it. Example: if I
618 * have a number (-)0x8000 (G_MINSHORT), then my abs()<<1
619 * will be 0x10000; this is G_MAXUSHORT+1! So: if (<0) -1. */
620 guint64 unum = (num < 0 ? (-num - 1) << 1 : num << 1);
621 guint size = gst_ebml_write_get_uint_size (unum);
623 buf = gst_ebml_write_element_new (ebml, &map, sizeof (num));
624 data_end = data_start = map.data;
630 unum = ((guint64) 0x80) << ((size - 1) * 8);
632 unum |= ((guint64) 0x80) << ((size - 1) * 8);
636 gst_ebml_write_element_id (&data_end, id);
637 gst_ebml_write_element_size (&data_end, size);
638 gst_ebml_write_set_uint (&data_end, unum, size);
639 gst_buffer_unmap (buf, &map);
640 gst_buffer_set_size (buf, (data_end - data_start));
642 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
647 * gst_ebml_write_float:
648 * @ebml: #GstEbmlWrite
650 * @num: Number to be written.
652 * Write float element.
655 gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
659 guint8 *data_start, *data_end;
661 buf = gst_ebml_write_element_new (ebml, &map, sizeof (num));
662 data_end = data_start = map.data;
664 gst_ebml_write_element_id (&data_end, id);
665 gst_ebml_write_element_size (&data_end, 8);
666 num = GDOUBLE_TO_BE (num);
667 gst_ebml_write_element_data (&data_end, (guint8 *) & num, 8);
668 gst_buffer_unmap (buf, &map);
669 gst_buffer_set_size (buf, (data_end - data_start));
671 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
676 * gst_ebml_write_ascii:
677 * @ebml: #GstEbmlWrite
679 * @str: String to be written.
681 * Write string element.
684 gst_ebml_write_ascii (GstEbmlWrite * ebml, guint32 id, const gchar * str)
686 gint len = strlen (str) + 1; /* add trailing '\0' */
689 guint8 *data_start, *data_end;
691 buf = gst_ebml_write_element_new (ebml, &map, len);
692 data_end = data_start = map.data;
694 gst_ebml_write_element_id (&data_end, id);
695 gst_ebml_write_element_size (&data_end, len);
696 gst_ebml_write_element_data (&data_end, (guint8 *) str, len);
697 gst_buffer_unmap (buf, &map);
698 gst_buffer_set_size (buf, (data_end - data_start));
700 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
705 * gst_ebml_write_utf8:
706 * @ebml: #GstEbmlWrite
708 * @str: String to be written.
710 * Write utf8 encoded string element.
713 gst_ebml_write_utf8 (GstEbmlWrite * ebml, guint32 id, const gchar * str)
715 gst_ebml_write_ascii (ebml, id, str);
720 * gst_ebml_write_date:
721 * @ebml: #GstEbmlWrite
723 * @date: Date in seconds since the unix epoch.
725 * Write date element.
728 gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date)
730 gst_ebml_write_sint (ebml, id, (date - GST_EBML_DATE_OFFSET) * GST_SECOND);
734 * gst_ebml_write_master_start:
735 * @ebml: #GstEbmlWrite
738 * Start wiriting mater element.
740 * Master writing is annoying. We use a size marker of
741 * the max. allowed length, so that we can later fill it
744 * Returns: Master starting position.
747 gst_ebml_write_master_start (GstEbmlWrite * ebml, guint32 id)
749 guint64 pos = ebml->pos;
752 guint8 *data_start, *data_end;
754 buf = gst_ebml_write_element_new (ebml, &map, 0);
755 data_end = data_start = map.data;
757 gst_ebml_write_element_id (&data_end, id);
758 pos += data_end - data_start;
759 gst_ebml_write_element_size (&data_end, GST_EBML_SIZE_UNKNOWN);
760 gst_buffer_unmap (buf, &map);
761 gst_buffer_set_size (buf, (data_end - data_start));
763 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
770 * gst_ebml_write_master_finish_full:
771 * @ebml: #GstEbmlWrite
772 * @startpos: Master starting position.
774 * Finish writing master element. Size of master element is difference between
775 * current position and the element start, and @extra_size added to this.
778 gst_ebml_write_master_finish_full (GstEbmlWrite * ebml, guint64 startpos,
781 guint64 pos = ebml->pos;
782 guint8 *data = g_malloc (8);
783 GstBuffer *buf = gst_buffer_new_wrapped (data, 8);
785 gst_ebml_write_seek (ebml, startpos);
787 GST_WRITE_UINT64_BE (data,
788 (G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8 + extra_size));
790 gst_ebml_write_element_push (ebml, buf, NULL, NULL);
791 gst_ebml_write_seek (ebml, pos);
795 gst_ebml_write_master_finish (GstEbmlWrite * ebml, guint64 startpos)
797 gst_ebml_write_master_finish_full (ebml, startpos, 0);
801 * gst_ebml_write_binary:
802 * @ebml: #GstEbmlWrite
804 * @binary: Data to be written.
805 * @length: Length of the data
807 * Write an element with binary data.
810 gst_ebml_write_binary (GstEbmlWrite * ebml,
811 guint32 id, guint8 * binary, guint64 length)
815 guint8 *data_start, *data_end;
817 buf = gst_ebml_write_element_new (ebml, &map, length);
818 data_end = data_start = map.data;
820 gst_ebml_write_element_id (&data_end, id);
821 gst_ebml_write_element_size (&data_end, length);
822 gst_ebml_write_element_data (&data_end, binary, length);
823 gst_buffer_unmap (buf, &map);
824 gst_buffer_set_size (buf, (data_end - data_start));
826 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
831 * gst_ebml_write_buffer_header:
832 * @ebml: #GstEbmlWrite
834 * @length: Length of the data
836 * Write header of the binary element (use with gst_ebml_write_buffer function).
838 * For things like video frames and audio samples,
839 * you want to use this function, as it doesn't have
840 * the overhead of memcpy() that other functions
841 * such as write_binary() do have.
844 gst_ebml_write_buffer_header (GstEbmlWrite * ebml, guint32 id, guint64 length)
848 guint8 *data_start, *data_end;
850 buf = gst_ebml_write_element_new (ebml, &map, 0);
851 data_end = data_start = map.data;
853 gst_ebml_write_element_id (&data_end, id);
854 gst_ebml_write_element_size (&data_end, length);
855 gst_buffer_unmap (buf, &map);
856 gst_buffer_set_size (buf, (data_end - data_start));
858 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
863 * gst_ebml_write_buffer:
864 * @ebml: #GstEbmlWrite
865 * @buf: #GstBuffer cointaining the data.
867 * Write binary element (see gst_ebml_write_buffer_header).
870 gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * buf)
872 gst_ebml_write_element_push (ebml, buf, NULL, NULL);
877 * gst_ebml_replace_uint:
878 * @ebml: #GstEbmlWrite
879 * @pos: Position of the uint that should be replaced.
882 * Replace uint with a new value.
884 * When replacing a uint, we assume that it is *always*
885 * 8-byte, since that's the safest guess we can do. This
886 * is just for simplicity.
888 * FIXME: this function needs to be replaced with something
889 * proper. This is a crude hack.
892 gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
894 guint64 oldpos = ebml->pos;
895 guint8 *data_start, *data_end;
898 data_start = g_malloc (8);
899 data_end = data_start;
900 buf = gst_buffer_new_wrapped (data_start, 8);
902 gst_ebml_write_seek (ebml, pos);
903 gst_ebml_write_set_uint (&data_end, num, 8);
905 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
906 gst_ebml_write_seek (ebml, oldpos);
910 * gst_ebml_write_header:
911 * @ebml: #GstEbmlWrite
912 * @doctype: Document type.
913 * @version: Document type version.
918 gst_ebml_write_header (GstEbmlWrite * ebml, const gchar * doctype,
923 /* write the basic EBML header */
924 gst_ebml_write_set_cache (ebml, 0x40);
925 pos = gst_ebml_write_master_start (ebml, GST_EBML_ID_HEADER);
926 #if (GST_EBML_VERSION != 1)
927 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLVERSION, GST_EBML_VERSION);
928 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLREADVERSION, GST_EBML_VERSION);
931 /* we don't write these until they're "non-default" (never!) */
932 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXIDLENGTH, sizeof (guint32));
933 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXSIZELENGTH, sizeof (guint64));
935 gst_ebml_write_ascii (ebml, GST_EBML_ID_DOCTYPE, doctype);
936 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEVERSION, version);
937 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
938 gst_ebml_write_master_finish (ebml, pos);
939 gst_ebml_write_flush_cache (ebml, FALSE, 0);