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.
29 #include "ebml-write.h"
33 GST_DEBUG_CATEGORY_STATIC (gst_ebml_write_debug);
34 #define GST_CAT_DEFAULT gst_ebml_write_debug
36 #define _do_init(thing) \
37 GST_DEBUG_CATEGORY_INIT (gst_ebml_write_debug, "ebmlwrite", 0, "Write EBML structured data")
38 GST_BOILERPLATE_FULL (GstEbmlWrite, gst_ebml_write, GstObject, GST_TYPE_OBJECT,
41 static void gst_ebml_write_finalize (GObject * object);
44 gst_ebml_write_base_init (gpointer g_class)
49 gst_ebml_write_class_init (GstEbmlWriteClass * klass)
51 GObjectClass *object = G_OBJECT_CLASS (klass);
53 object->finalize = gst_ebml_write_finalize;
57 gst_ebml_write_init (GstEbmlWrite * ebml, GstEbmlWriteClass * klass)
61 ebml->last_pos = G_MAXUINT64; /* force newsegment event */
64 ebml->streamheader = NULL;
65 ebml->streamheader_pos = 0;
66 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;
88 gst_caps_unref (ebml->caps);
92 GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
98 * @srcpad: Source pad to which the output will be pushed.
100 * Creates a new #GstEbmlWrite.
102 * Returns: a new #GstEbmlWrite
105 gst_ebml_write_new (GstPad * srcpad)
108 GST_EBML_WRITE (g_object_new (GST_TYPE_EBML_WRITE, NULL));
110 ebml->srcpad = gst_object_ref (srcpad);
111 ebml->timestamp = GST_CLOCK_TIME_NONE;
113 gst_ebml_write_reset (ebml);
120 * gst_ebml_write_reset:
121 * @ebml: a #GstEbmlWrite.
123 * Reset internal state of #GstEbmlWrite.
126 gst_ebml_write_reset (GstEbmlWrite * ebml)
129 ebml->last_pos = G_MAXUINT64; /* force newsegment event */
132 gst_byte_writer_free (ebml->cache);
137 gst_caps_unref (ebml->caps);
141 ebml->last_write_result = GST_FLOW_OK;
142 ebml->timestamp = GST_CLOCK_TIME_NONE;
147 * gst_ebml_last_write_result:
148 * @ebml: a #GstEbmlWrite.
150 * Returns: GST_FLOW_OK if there was not write error since the last call of
151 * gst_ebml_last_write_result or code of the error.
154 gst_ebml_last_write_result (GstEbmlWrite * ebml)
156 GstFlowReturn res = ebml->last_write_result;
158 ebml->last_write_result = GST_FLOW_OK;
165 gst_ebml_start_streamheader (GstEbmlWrite * ebml)
167 g_return_if_fail (ebml->streamheader == NULL);
169 GST_DEBUG ("Starting streamheader at %" G_GUINT64_FORMAT, ebml->pos);
170 ebml->streamheader = gst_byte_writer_new_with_size (1000, FALSE);
171 ebml->streamheader_pos = ebml->pos;
172 ebml->writing_streamheader = TRUE;
176 gst_ebml_stop_streamheader (GstEbmlWrite * ebml)
180 if (!ebml->streamheader)
183 buffer = gst_byte_writer_free_and_get_buffer (ebml->streamheader);
184 ebml->streamheader = NULL;
185 GST_DEBUG ("Streamheader was size %d", GST_BUFFER_SIZE (buffer));
187 ebml->writing_streamheader = FALSE;
192 * gst_ebml_write_set_cache:
193 * @ebml: a #GstEbmlWrite.
194 * @size: size of the cache.
197 * The idea is that you use this for writing a lot
198 * of small elements. This will just "queue" all of
199 * them and they'll be pushed to the next element all
200 * at once. This saves memory and time for buffer
201 * allocation and init, and it looks better.
204 gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
206 g_return_if_fail (ebml->cache == NULL);
208 GST_DEBUG ("Starting cache at %" G_GUINT64_FORMAT, ebml->pos);
209 ebml->cache = gst_byte_writer_new_with_size (size, FALSE);
210 ebml->cache_pos = ebml->pos;
214 gst_ebml_writer_send_new_segment_event (GstEbmlWrite * ebml, guint64 new_pos)
218 GST_INFO ("seeking to %" G_GUINT64_FORMAT, new_pos);
220 res = gst_pad_push_event (ebml->srcpad,
221 gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, new_pos, -1, 0));
224 GST_WARNING ("seek to %" G_GUINT64_FORMAT "failed", new_pos);
230 * gst_ebml_write_flush_cache:
231 * @ebml: a #GstEbmlWrite.
232 * @timestamp: timestamp of the buffer.
237 gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe,
238 GstClockTime timestamp)
245 buffer = gst_byte_writer_free_and_get_buffer (ebml->cache);
247 GST_DEBUG ("Flushing cache of size %d", GST_BUFFER_SIZE (buffer));
248 gst_buffer_set_caps (buffer, ebml->caps);
249 GST_BUFFER_TIMESTAMP (buffer) = timestamp;
250 GST_BUFFER_OFFSET (buffer) = ebml->pos - GST_BUFFER_SIZE (buffer);
251 GST_BUFFER_OFFSET_END (buffer) = ebml->pos;
252 if (ebml->last_write_result == GST_FLOW_OK) {
253 if (GST_BUFFER_OFFSET (buffer) != ebml->last_pos) {
254 gst_ebml_writer_send_new_segment_event (ebml, GST_BUFFER_OFFSET (buffer));
255 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
257 if (ebml->writing_streamheader) {
258 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
261 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
263 ebml->last_pos = ebml->pos;
264 ebml->last_write_result = gst_pad_push (ebml->srcpad, buffer);
266 gst_buffer_unref (buffer);
272 * gst_ebml_write_element_new:
273 * @ebml: a #GstEbmlWrite.
274 * @size: size of the requested buffer.
276 * Create a buffer for one element. If there is
277 * a cache, use that instead.
279 * Returns: A new #GstBuffer.
282 gst_ebml_write_element_new (GstEbmlWrite * ebml, guint8 ** data_out, guint size)
284 /* Create new buffer of size + ID + length */
290 buf = gst_buffer_new_and_alloc (size);
291 GST_BUFFER_TIMESTAMP (buf) = ebml->timestamp;
293 *data_out = GST_BUFFER_DATA (buf);
300 * gst_ebml_write_element_id:
301 * @data_inout: Pointer to data pointer
302 * @id: Element ID that should be written.
304 * Write element ID into a buffer.
307 gst_ebml_write_element_id (guint8 ** data_inout, guint32 id)
309 guint8 *data = *data_inout;
310 guint bytes = 4, mask = 0x10;
313 while (!(id & (mask << ((bytes - 1) * 8))) && bytes > 0) {
318 /* if invalid ID, use dummy */
320 GST_WARNING ("Invalid ID, voiding");
322 id = GST_EBML_ID_VOID;
326 *data_inout += bytes;
328 data[bytes] = id & 0xff;
335 * gst_ebml_write_element_size:
336 * @data_inout: Pointer to data pointer
337 * @size: Element length.
339 * Write element length into a buffer.
342 gst_ebml_write_element_size (guint8 ** data_inout, guint64 size)
344 guint8 *data = *data_inout;
345 guint bytes = 1, mask = 0x80;
347 if (size != GST_EBML_SIZE_UNKNOWN) {
348 /* how many bytes? - use mask-1 because an all-1 bitset is not allowed */
349 while ((size >> ((bytes - 1) * 8)) >= (mask - 1) && bytes <= 8) {
354 /* if invalid size, use max. */
356 GST_WARNING ("Invalid size, writing size unknown");
359 /* Now here's a real FIXME: we cannot read those yet! */
360 size = GST_EBML_SIZE_UNKNOWN;
367 /* write out, BE, with length size marker */
368 *data_inout += bytes;
369 while (bytes-- > 0) {
370 data[bytes] = size & 0xff;
379 * gst_ebml_write_element_data:
380 * @data_inout: Pointer to data pointer
381 * @write: Data that should be written.
382 * @length: Length of the data.
384 * Write element data into a buffer.
387 gst_ebml_write_element_data (guint8 ** data_inout, guint8 * write,
390 memcpy (*data_inout, write, length);
391 *data_inout += length;
396 * gst_ebml_write_element_push:
397 * @ebml: #GstEbmlWrite
398 * @buf: #GstBuffer to be written.
399 * @buf_data: Start of data to push from @buf (or NULL for whole buffer).
400 * @buf_data_end: Data pointer positioned after the last byte in @buf_data (or
401 * NULL for whole buffer).
403 * Write out buffer by moving it to the next element.
406 gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf,
407 guint8 * buf_data, guint8 * buf_data_end)
412 buf_data = GST_BUFFER_DATA (buf);
415 data_size = buf_data_end - buf_data;
416 GST_BUFFER_SIZE (buf) = data_size;
418 data_size = GST_BUFFER_SIZE (buf);
421 ebml->pos += data_size;
423 /* if there's no cache, then don't push it! */
424 if (ebml->writing_streamheader) {
425 gst_byte_writer_put_data (ebml->streamheader, buf_data, data_size);
428 gst_byte_writer_put_data (ebml->cache, buf_data, data_size);
429 gst_buffer_unref (buf);
433 if (ebml->last_write_result == GST_FLOW_OK) {
434 buf = gst_buffer_make_metadata_writable (buf);
435 gst_buffer_set_caps (buf, ebml->caps);
436 GST_BUFFER_OFFSET (buf) = ebml->pos - data_size;
437 GST_BUFFER_OFFSET_END (buf) = ebml->pos;
438 if (ebml->writing_streamheader) {
439 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
441 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
443 if (GST_BUFFER_OFFSET (buf) != ebml->last_pos) {
444 gst_ebml_writer_send_new_segment_event (ebml, GST_BUFFER_OFFSET (buf));
445 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
447 ebml->last_pos = ebml->pos;
448 ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
450 gst_buffer_unref (buf);
456 * gst_ebml_write_seek:
457 * @ebml: #GstEbmlWrite
458 * @pos: Seek position.
463 gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
465 if (ebml->writing_streamheader) {
466 GST_DEBUG ("wanting to seek to pos %" G_GUINT64_FORMAT, pos);
467 if (pos >= ebml->streamheader_pos &&
468 pos <= ebml->streamheader_pos + ebml->streamheader->parent.size) {
469 gst_byte_writer_set_pos (ebml->streamheader,
470 pos - ebml->streamheader_pos);
471 GST_DEBUG ("seeked in streamheader to position %" G_GUINT64_FORMAT,
472 pos - ebml->streamheader_pos);
475 ("we are writing streamheader still and seek is out of bounds");
478 /* Cache seeking. A bit dangerous, we assume the client writer
479 * knows what he's doing... */
482 if (pos >= ebml->cache_pos &&
483 pos <= ebml->cache_pos + ebml->cache->parent.size) {
484 GST_DEBUG ("seeking in cache to %" G_GUINT64_FORMAT, pos);
486 gst_byte_writer_set_pos (ebml->cache, ebml->pos - ebml->cache_pos);
489 GST_LOG ("Seek outside cache range. Clearing...");
490 gst_ebml_write_flush_cache (ebml, FALSE, GST_CLOCK_TIME_NONE);
494 GST_INFO ("scheduling seek to %" G_GUINT64_FORMAT, pos);
500 * gst_ebml_write_get_uint_size:
501 * @num: Number to be encoded.
503 * Get number of bytes needed to write a uint.
505 * Returns: Encoded uint length.
508 gst_ebml_write_get_uint_size (guint64 num)
513 while (num >= (G_GINT64_CONSTANT (1) << (size * 8)) && size < 8) {
522 * gst_ebml_write_set_uint:
523 * @data_inout: Pointer to data pointer
524 * @num: Number to be written.
525 * @size: Encoded number length.
527 * Write an uint into a buffer.
530 gst_ebml_write_set_uint (guint8 ** data_inout, guint64 num, guint size)
532 guint8 *data = *data_inout;
537 data[size] = num & 0xff;
544 * gst_ebml_write_uint:
545 * @ebml: #GstEbmlWrite
547 * @num: Number to be written.
549 * Write uint element.
552 gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num)
555 guint8 *data_start, *data_end;
556 guint size = gst_ebml_write_get_uint_size (num);
558 buf = gst_ebml_write_element_new (ebml, &data_start, sizeof (num));
559 data_end = data_start;
562 gst_ebml_write_element_id (&data_end, id);
563 gst_ebml_write_element_size (&data_end, size);
564 gst_ebml_write_set_uint (&data_end, num, size);
565 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
570 * gst_ebml_write_sint:
571 * @ebml: #GstEbmlWrite
573 * @num: Number to be written.
575 * Write sint element.
578 gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
581 guint8 *data_start, *data_end;
582 /* if the signed number is on the edge of a extra-byte,
583 * then we'll fall over when detecting it. Example: if I
584 * have a number (-)0x8000 (G_MINSHORT), then my abs()<<1
585 * will be 0x10000; this is G_MAXUSHORT+1! So: if (<0) -1. */
586 guint64 unum = (num < 0 ? (-num - 1) << 1 : num << 1);
587 guint size = gst_ebml_write_get_uint_size (unum);
589 buf = gst_ebml_write_element_new (ebml, &data_start, sizeof (num));
590 data_end = data_start;
596 unum = 0x80 << (size - 1);
598 unum |= 0x80 << (size - 1);
602 gst_ebml_write_element_id (&data_end, id);
603 gst_ebml_write_element_size (&data_end, size);
604 gst_ebml_write_set_uint (&data_end, unum, size);
605 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
610 * gst_ebml_write_float:
611 * @ebml: #GstEbmlWrite
613 * @num: Number to be written.
615 * Write float element.
618 gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
621 guint8 *data_start, *data_end;
623 buf = gst_ebml_write_element_new (ebml, &data_start, sizeof (num));
624 data_end = data_start;
626 gst_ebml_write_element_id (&data_end, id);
627 gst_ebml_write_element_size (&data_end, 8);
628 num = GDOUBLE_TO_BE (num);
629 gst_ebml_write_element_data (&data_end, (guint8 *) & num, 8);
630 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
635 * gst_ebml_write_ascii:
636 * @ebml: #GstEbmlWrite
638 * @str: String to be written.
640 * Write string element.
643 gst_ebml_write_ascii (GstEbmlWrite * ebml, guint32 id, const gchar * str)
645 gint len = strlen (str) + 1; /* add trailing '\0' */
647 guint8 *data_start, *data_end;
649 buf = gst_ebml_write_element_new (ebml, &data_start, len);
650 data_end = data_start;
652 gst_ebml_write_element_id (&data_end, id);
653 gst_ebml_write_element_size (&data_end, len);
654 gst_ebml_write_element_data (&data_end, (guint8 *) str, len);
655 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
660 * gst_ebml_write_utf8:
661 * @ebml: #GstEbmlWrite
663 * @str: String to be written.
665 * Write utf8 encoded string element.
668 gst_ebml_write_utf8 (GstEbmlWrite * ebml, guint32 id, const gchar * str)
670 gst_ebml_write_ascii (ebml, id, str);
675 * gst_ebml_write_date:
676 * @ebml: #GstEbmlWrite
678 * @date: Date in seconds since the unix epoch.
680 * Write date element.
683 gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date)
685 gst_ebml_write_sint (ebml, id, (date - GST_EBML_DATE_OFFSET) * GST_SECOND);
689 * gst_ebml_write_master_start:
690 * @ebml: #GstEbmlWrite
693 * Start wiriting mater element.
695 * Master writing is annoying. We use a size marker of
696 * the max. allowed length, so that we can later fill it
699 * Returns: Master starting position.
702 gst_ebml_write_master_start (GstEbmlWrite * ebml, guint32 id)
704 guint64 pos = ebml->pos;
706 guint8 *data_start, *data_end;
708 buf = gst_ebml_write_element_new (ebml, &data_start, 0);
709 data_end = data_start;
711 gst_ebml_write_element_id (&data_end, id);
712 pos += data_end - data_start;
713 gst_ebml_write_element_size (&data_end, GST_EBML_SIZE_UNKNOWN);
714 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
721 * gst_ebml_write_master_finish_full:
722 * @ebml: #GstEbmlWrite
723 * @startpos: Master starting position.
725 * Finish writing master element. Size of master element is difference between
726 * current position and the element start, and @extra_size added to this.
729 gst_ebml_write_master_finish_full (GstEbmlWrite * ebml, guint64 startpos,
732 guint64 pos = ebml->pos;
735 gst_ebml_write_seek (ebml, startpos);
737 buf = gst_buffer_new_and_alloc (8);
738 GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf),
739 (G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8 + extra_size));
741 gst_ebml_write_element_push (ebml, buf, NULL, NULL);
742 gst_ebml_write_seek (ebml, pos);
746 gst_ebml_write_master_finish (GstEbmlWrite * ebml, guint64 startpos)
748 gst_ebml_write_master_finish_full (ebml, startpos, 0);
752 * gst_ebml_write_binary:
753 * @ebml: #GstEbmlWrite
755 * @binary: Data to be written.
756 * @length: Length of the data
758 * Write an element with binary data.
761 gst_ebml_write_binary (GstEbmlWrite * ebml,
762 guint32 id, guint8 * binary, guint64 length)
765 guint8 *data_start, *data_end;
767 buf = gst_ebml_write_element_new (ebml, &data_start, length);
768 data_end = data_start;
770 gst_ebml_write_element_id (&data_end, id);
771 gst_ebml_write_element_size (&data_end, length);
772 gst_ebml_write_element_data (&data_end, binary, length);
773 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
778 * gst_ebml_write_buffer_header:
779 * @ebml: #GstEbmlWrite
781 * @length: Length of the data
783 * Write header of the binary element (use with gst_ebml_write_buffer function).
785 * For things like video frames and audio samples,
786 * you want to use this function, as it doesn't have
787 * the overhead of memcpy() that other functions
788 * such as write_binary() do have.
791 gst_ebml_write_buffer_header (GstEbmlWrite * ebml, guint32 id, guint64 length)
794 guint8 *data_start, *data_end;
796 buf = gst_ebml_write_element_new (ebml, &data_start, 0);
797 data_end = data_start;
799 gst_ebml_write_element_id (&data_end, id);
800 gst_ebml_write_element_size (&data_end, length);
801 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
806 * gst_ebml_write_buffer:
807 * @ebml: #GstEbmlWrite
808 * @buf: #GstBuffer cointaining the data.
810 * Write binary element (see gst_ebml_write_buffer_header).
813 gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * buf)
815 gst_ebml_write_element_push (ebml, buf, NULL, NULL);
820 * gst_ebml_replace_uint:
821 * @ebml: #GstEbmlWrite
822 * @pos: Position of the uint that should be replaced.
825 * Replace uint with a new value.
827 * When replacing a uint, we assume that it is *always*
828 * 8-byte, since that's the safest guess we can do. This
829 * is just for simplicity.
831 * FIXME: this function needs to be replaced with something
832 * proper. This is a crude hack.
835 gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
837 guint64 oldpos = ebml->pos;
838 GstBuffer *buf = gst_buffer_new_and_alloc (8);
839 guint8 *data_start, *data_end;
841 data_start = GST_BUFFER_DATA (buf);
842 data_end = data_start;
844 gst_ebml_write_seek (ebml, pos);
845 gst_ebml_write_set_uint (&data_end, num, 8);
847 gst_ebml_write_element_push (ebml, buf, data_start, data_end);
848 gst_ebml_write_seek (ebml, oldpos);
852 * gst_ebml_write_header:
853 * @ebml: #GstEbmlWrite
854 * @doctype: Document type.
855 * @version: Document type version.
860 gst_ebml_write_header (GstEbmlWrite * ebml, const gchar * doctype,
865 /* write the basic EBML header */
866 gst_ebml_write_set_cache (ebml, 0x40);
867 pos = gst_ebml_write_master_start (ebml, GST_EBML_ID_HEADER);
868 #if (GST_EBML_VERSION != 1)
869 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLVERSION, GST_EBML_VERSION);
870 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLREADVERSION, GST_EBML_VERSION);
873 /* we don't write these until they're "non-default" (never!) */
874 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXIDLENGTH, sizeof (guint32));
875 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXSIZELENGTH, sizeof (guint64));
877 gst_ebml_write_ascii (ebml, GST_EBML_ID_DOCTYPE, doctype);
878 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEVERSION, version);
879 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
880 gst_ebml_write_master_finish (ebml, pos);
881 gst_ebml_write_flush_cache (ebml, FALSE, 0);