2 * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * ebml-write.c: write EBML data to file/stream
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
28 #include "ebml-write.h"
36 static void gst_ebml_write_class_init (GstEbmlWriteClass *klass);
37 static void gst_ebml_write_init (GstEbmlWrite *ebml);
38 static GstElementStateReturn
39 gst_ebml_write_change_state (GstElement *element);
41 static GstElementClass *parent_class = NULL;
44 gst_ebml_write_get_type (void)
46 static GType gst_ebml_write_type = 0;
48 if (!gst_ebml_write_type) {
49 static const GTypeInfo gst_ebml_write_info = {
50 sizeof (GstEbmlWriteClass),
53 (GClassInitFunc) gst_ebml_write_class_init,
56 sizeof (GstEbmlWrite),
58 (GInstanceInitFunc) gst_ebml_write_init,
62 g_type_register_static (GST_TYPE_ELEMENT, "GstEbmlWrite",
63 &gst_ebml_write_info, 0);
66 return gst_ebml_write_type;
70 gst_ebml_write_class_init (GstEbmlWriteClass *klass)
72 GstElementClass *gstelement_class = (GstElementClass *) klass;
74 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
76 gstelement_class->change_state = gst_ebml_write_change_state;
80 gst_ebml_write_init (GstEbmlWrite *ebml)
88 static GstElementStateReturn
89 gst_ebml_write_change_state (GstElement *element)
91 GstEbmlWrite *ebml = GST_EBML_WRITE (element);
93 switch (GST_STATE_TRANSITION (element)) {
94 case GST_STATE_PAUSED_TO_READY:
101 if (GST_ELEMENT_CLASS (parent_class)->change_state)
102 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
104 return GST_STATE_SUCCESS;
110 * The idea is that you use this for writing a lot
111 * of small elements. This will just "queue" all of
112 * them and they'll be pushed to the next element all
113 * at once. This saves memory and time for buffer
114 * allocation and init, and it looks better.
118 gst_ebml_write_set_cache (GstEbmlWrite *ebml,
121 /* This is currently broken. I don't know why yet. */
124 g_return_if_fail (ebml->cache == NULL);
126 ebml->cache = gst_buffer_new_and_alloc (size);
127 GST_BUFFER_SIZE (ebml->cache) = 0;
128 GST_BUFFER_OFFSET (ebml->cache) = ebml->pos;
133 gst_ebml_write_flush_cache (GstEbmlWrite *ebml)
138 /* this is very important. It may fail, in which case the client
139 * programmer didn't use the cache somewhere. That's fatal. */
140 g_assert (ebml->handled == GST_BUFFER_SIZE (ebml->cache));
141 g_assert (GST_BUFFER_SIZE (ebml->cache) +
142 GST_BUFFER_OFFSET (ebml->cache) == ebml->pos);
144 gst_pad_push (ebml->srcpad, GST_DATA (ebml->cache));
150 * One-element buffer, in case of no cache. If there is
151 * a cache, use that instead.
155 gst_ebml_write_element_new (GstEbmlWrite *ebml,
158 /* Create new buffer of size + ID + length */
166 if (GST_BUFFER_MAXSIZE (ebml->cache) -
167 GST_BUFFER_SIZE (ebml->cache) < size) {
168 GST_LOG ("Cache available, but too small. Clearing...");
169 gst_ebml_write_flush_cache (ebml);
175 /* else, use a one-element buffer. This is slower */
176 buf = gst_buffer_new_and_alloc (size);
177 GST_BUFFER_SIZE (buf) = 0;
183 * Write element ID into a buffer.
187 gst_ebml_write_element_id (GstBuffer *buf,
190 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
191 guint bytes = 4, mask = 0x10;
194 while (!(id & (mask << ((bytes - 1) * 8))) && bytes > 0) {
199 /* if invalid ID, use dummy */
201 GST_WARNING ("Invalid ID, voiding");
203 id = GST_EBML_ID_VOID;
207 GST_BUFFER_SIZE (buf) += bytes;
209 data[bytes] = id & 0xff;
215 * Write element length into a buffer.
219 gst_ebml_write_element_size (GstBuffer *buf,
222 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
223 guint bytes = 1, mask = 0x80;
225 /* how many bytes? */
226 while ((size >> ((bytes - 1) * 8)) >= mask && bytes <= 8) {
231 /* if invalid size, use max. */
233 GST_WARNING ("Invalid size, maximizing");
236 /* Now here's a real FIXME: we cannot read those yet! */
237 size = 0x00ffffffffffffffLLU;
240 /* write out, BE, with length size marker */
241 GST_BUFFER_SIZE (buf) += bytes;
242 while (bytes-- > 0) {
243 data[bytes] = size & 0xff;
251 * Write element data into a buffer.
255 gst_ebml_write_element_data (GstBuffer *buf,
259 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
261 memcpy (data, write, length);
262 GST_BUFFER_SIZE (buf) += length;
266 * Write out buffer by moving it to the next element.
270 gst_ebml_write_element_push (GstEbmlWrite *ebml,
273 guint data_size = GST_BUFFER_SIZE (buf) - ebml->handled;
275 ebml->pos += data_size;
276 if (buf == ebml->cache) {
277 ebml->handled += data_size;
280 /* if there's no cache, then don't push it! */
282 g_assert (buf == ebml->cache);
286 gst_pad_push (ebml->srcpad, GST_DATA (buf));
294 gst_ebml_write_seek (GstEbmlWrite *ebml,
299 /* Cache seeking. A bit dangerous, we assume the client writer
300 * knows what he's doing... */
303 if (pos >= GST_BUFFER_OFFSET (ebml->cache) &&
304 pos < GST_BUFFER_OFFSET (ebml->cache) + GST_BUFFER_MAXSIZE (ebml->cache)) {
305 GST_BUFFER_SIZE (ebml->cache) = pos - GST_BUFFER_OFFSET (ebml->cache);
307 ebml->handled -= ebml->pos - pos;
309 ebml->handled += pos - ebml->pos;
312 GST_LOG ("Seek outside cache range. Clearing...");
313 gst_ebml_write_flush_cache (ebml);
317 seek = gst_event_new_seek (GST_FORMAT_BYTES |
320 gst_pad_push (ebml->srcpad, GST_DATA (seek));
325 * Get no. bytes needed to write a uint.
329 gst_ebml_write_get_uint_size (guint64 num)
334 while (num >= (1LLU << (size * 8)) && size < 8) {
343 * Write an uint into a buffer.
347 gst_ebml_write_set_uint (GstBuffer *buf,
353 data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
354 GST_BUFFER_SIZE (buf) += size;
356 data[size] = num & 0xff;
362 * Data type wrappers.
366 gst_ebml_write_uint (GstEbmlWrite *ebml,
370 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
371 guint size = gst_ebml_write_get_uint_size (num);
374 gst_ebml_write_element_id (buf, id);
375 gst_ebml_write_element_size (buf, size);
376 gst_ebml_write_set_uint (buf, num, size);
377 gst_ebml_write_element_push (ebml, buf);
381 gst_ebml_write_sint (GstEbmlWrite *ebml,
385 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
386 /* if the signed number is on the edge of a extra-byte,
387 * then we'll fall over when detecting it. Example: if I
388 * have a number (-)0x8000 (G_MINSHORT), then my abs()<<1
389 * will be 0x10000; this is G_MAXUSHORT+1! So: if (<0) -1. */
390 guint64 unum = (num < 0 ? (-num - 1) << 1 : num << 1);
391 guint size = gst_ebml_write_get_uint_size (unum);
397 unum = 0x80 << (size - 1);
399 unum |= 0x80 << (size - 1);
403 gst_ebml_write_element_id (buf, id);
404 gst_ebml_write_element_size (buf, size);
405 gst_ebml_write_set_uint (buf, unum, size);
406 gst_ebml_write_element_push (ebml, buf);
410 gst_ebml_write_float (GstEbmlWrite *ebml,
414 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
417 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
419 gst_ebml_write_element_id (buf, id);
420 gst_ebml_write_element_size (buf, 8);
421 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
422 for (n = 0; n < 8; n++)
423 GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf)] = ((guint8 *) &num)[7-n];
424 GST_BUFFER_SIZE (buf) += 8;
426 gst_ebml_write_element_data (buf, (guint8 *) &num, 8);
428 gst_ebml_write_element_push (ebml, buf);
432 gst_ebml_write_ascii (GstEbmlWrite *ebml,
436 gint len = strlen (str) + 1; /* add trailing '\0' */
437 GstBuffer *buf = gst_ebml_write_element_new (ebml, len);
439 gst_ebml_write_element_id (buf, id);
440 gst_ebml_write_element_size (buf, len);
441 gst_ebml_write_element_data (buf, (guint8 *) str, len);
442 gst_ebml_write_element_push (ebml, buf);
446 gst_ebml_write_utf8 (GstEbmlWrite *ebml,
450 gst_ebml_write_ascii (ebml, id, str);
454 gst_ebml_write_date (GstEbmlWrite *ebml,
458 gst_ebml_write_sint (ebml, id, date);
462 * Master writing is annoying. We use a size marker of
463 * the max. allowed length, so that we can later fill it
468 gst_ebml_write_master_start (GstEbmlWrite *ebml,
471 guint64 pos = ebml->pos, t;
472 GstBuffer *buf = gst_ebml_write_element_new (ebml, 0);
474 t = GST_BUFFER_SIZE (buf);
475 gst_ebml_write_element_id (buf, id);
476 pos += GST_BUFFER_SIZE (buf) - t;
477 gst_ebml_write_element_size (buf, -1);
478 gst_ebml_write_element_push (ebml, buf);
484 gst_ebml_write_master_finish (GstEbmlWrite *ebml,
487 guint64 pos = ebml->pos;
490 gst_ebml_write_seek (ebml, startpos);
491 buf = gst_ebml_write_element_new (ebml, 0);
492 startpos = GUINT64_TO_BE ((1LLU << 56) | (pos - startpos - 8));
493 memcpy (GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf),
494 (guint8 *) &startpos, 8);
495 GST_BUFFER_SIZE (buf) += 8;
496 gst_ebml_write_element_push (ebml, buf);
497 gst_ebml_write_seek (ebml, pos);
501 gst_ebml_write_binary (GstEbmlWrite *ebml,
506 GstBuffer *buf = gst_ebml_write_element_new (ebml, length);
508 gst_ebml_write_element_id (buf, id);
509 gst_ebml_write_element_size (buf, length);
510 gst_ebml_write_element_data (buf, binary, length);
511 gst_ebml_write_element_push (ebml, buf);
515 * For things like video frames and audio samples,
516 * you want to use this function, as it doesn't have
517 * the overhead of memcpy() that other functions
518 * such as write_binary() do have.
522 gst_ebml_write_buffer_header (GstEbmlWrite *ebml,
526 GstBuffer *buf = gst_ebml_write_element_new (ebml, 0);
528 gst_ebml_write_element_id (buf, id);
529 gst_ebml_write_element_size (buf, length);
530 gst_ebml_write_element_push (ebml, buf);
534 gst_ebml_write_buffer (GstEbmlWrite *ebml,
537 gst_ebml_write_element_push (ebml, data);
541 * When replacing a uint, we assume that it is *always*
542 * 8-byte, since that's the safest guess we can do. This
543 * is just for simplicity.
545 * FIXME: this function needs to be replaced with something
546 * proper. This is a crude hack.
550 gst_ebml_replace_uint (GstEbmlWrite *ebml,
554 guint64 oldpos = ebml->pos;
555 GstBuffer *buf = gst_buffer_new_and_alloc (8);
557 gst_ebml_write_seek (ebml, pos);
558 GST_BUFFER_SIZE (buf) = 0;
559 gst_ebml_write_set_uint (buf, num, 8);
560 gst_ebml_write_element_push (ebml, buf);
561 gst_ebml_write_seek (ebml, oldpos);
569 gst_ebml_write_header (GstEbmlWrite *ebml,
575 /* write the basic EBML header */
576 gst_ebml_write_set_cache (ebml, 0x40);
577 pos = gst_ebml_write_master_start (ebml, GST_EBML_ID_HEADER);
578 #if (GST_EBML_VERSION != 1)
579 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLVERSION, GST_EBML_VERSION);
580 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLREADVERSION, GST_EBML_VERSION);
583 /* we don't write these until they're "non-default" (never!) */
584 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXIDLENGTH, sizeof (guint32));
585 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXSIZELENGTH, sizeof (guint64));
587 gst_ebml_write_ascii (ebml, GST_EBML_ID_DOCTYPE, doctype);
588 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEVERSION, version);
589 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
590 gst_ebml_write_master_finish (ebml, pos);
591 gst_ebml_write_flush_cache (ebml);