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"
37 static void gst_ebml_write_class_init (GstEbmlWriteClass * klass);
38 static void gst_ebml_write_init (GstEbmlWrite * ebml);
39 static GstElementStateReturn 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, guint size)
120 /* This is currently broken. I don't know why yet. */
123 g_return_if_fail (ebml->cache == NULL);
125 ebml->cache = gst_buffer_new_and_alloc (size);
126 GST_BUFFER_SIZE (ebml->cache) = 0;
127 GST_BUFFER_OFFSET (ebml->cache) = ebml->pos;
132 gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
137 /* this is very important. It may fail, in which case the client
138 * programmer didn't use the cache somewhere. That's fatal. */
139 g_assert (ebml->handled == GST_BUFFER_SIZE (ebml->cache));
140 g_assert (GST_BUFFER_SIZE (ebml->cache) +
141 GST_BUFFER_OFFSET (ebml->cache) == ebml->pos);
143 gst_pad_push (ebml->srcpad, GST_DATA (ebml->cache));
149 * One-element buffer, in case of no cache. If there is
150 * a cache, use that instead.
154 gst_ebml_write_element_new (GstEbmlWrite * ebml, guint size)
156 /* Create new buffer of size + ID + length */
164 if (GST_BUFFER_MAXSIZE (ebml->cache) - GST_BUFFER_SIZE (ebml->cache) < size) {
165 GST_LOG ("Cache available, but too small. Clearing...");
166 gst_ebml_write_flush_cache (ebml);
172 /* else, use a one-element buffer. This is slower */
173 buf = gst_buffer_new_and_alloc (size);
174 GST_BUFFER_SIZE (buf) = 0;
180 * Write element ID into a buffer.
184 gst_ebml_write_element_id (GstBuffer * buf, guint32 id)
186 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
187 guint bytes = 4, mask = 0x10;
190 while (!(id & (mask << ((bytes - 1) * 8))) && bytes > 0) {
195 /* if invalid ID, use dummy */
197 GST_WARNING ("Invalid ID, voiding");
199 id = GST_EBML_ID_VOID;
203 GST_BUFFER_SIZE (buf) += bytes;
205 data[bytes] = id & 0xff;
211 * Write element length into a buffer.
215 gst_ebml_write_element_size (GstBuffer * buf, guint64 size)
217 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
218 guint bytes = 1, mask = 0x80;
220 /* how many bytes? */
221 while ((size >> ((bytes - 1) * 8)) >= mask && bytes <= 8) {
226 /* if invalid size, use max. */
228 GST_WARNING ("Invalid size, maximizing");
231 /* Now here's a real FIXME: we cannot read those yet! */
232 size = 0x00ffffffffffffffLLU;
235 /* write out, BE, with length size marker */
236 GST_BUFFER_SIZE (buf) += bytes;
237 while (bytes-- > 0) {
238 data[bytes] = size & 0xff;
246 * Write element data into a buffer.
250 gst_ebml_write_element_data (GstBuffer * buf, guint8 * write, guint64 length)
252 guint8 *data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
254 memcpy (data, write, length);
255 GST_BUFFER_SIZE (buf) += length;
259 * Write out buffer by moving it to the next element.
263 gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf)
265 guint data_size = GST_BUFFER_SIZE (buf) - ebml->handled;
267 ebml->pos += data_size;
268 if (buf == ebml->cache) {
269 ebml->handled += data_size;
272 /* if there's no cache, then don't push it! */
274 g_assert (buf == ebml->cache);
278 gst_pad_push (ebml->srcpad, GST_DATA (buf));
286 gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
290 /* Cache seeking. A bit dangerous, we assume the client writer
291 * knows what he's doing... */
294 if (pos >= GST_BUFFER_OFFSET (ebml->cache) &&
296 GST_BUFFER_OFFSET (ebml->cache) + GST_BUFFER_MAXSIZE (ebml->cache)) {
297 GST_BUFFER_SIZE (ebml->cache) = pos - GST_BUFFER_OFFSET (ebml->cache);
299 ebml->handled -= ebml->pos - pos;
301 ebml->handled += pos - ebml->pos;
304 GST_LOG ("Seek outside cache range. Clearing...");
305 gst_ebml_write_flush_cache (ebml);
309 seek = gst_event_new_seek (GST_FORMAT_BYTES | GST_SEEK_METHOD_SET, pos);
310 gst_pad_push (ebml->srcpad, GST_DATA (seek));
315 * Get no. bytes needed to write a uint.
319 gst_ebml_write_get_uint_size (guint64 num)
324 while (num >= (1LLU << (size * 8)) && size < 8) {
333 * Write an uint into a buffer.
337 gst_ebml_write_set_uint (GstBuffer * buf, guint64 num, guint size)
341 data = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);
342 GST_BUFFER_SIZE (buf) += size;
344 data[size] = num & 0xff;
350 * Data type wrappers.
354 gst_ebml_write_uint (GstEbmlWrite * ebml, guint32 id, guint64 num)
356 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
357 guint size = gst_ebml_write_get_uint_size (num);
360 gst_ebml_write_element_id (buf, id);
361 gst_ebml_write_element_size (buf, size);
362 gst_ebml_write_set_uint (buf, num, size);
363 gst_ebml_write_element_push (ebml, buf);
367 gst_ebml_write_sint (GstEbmlWrite * ebml, guint32 id, gint64 num)
369 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
371 /* if the signed number is on the edge of a extra-byte,
372 * then we'll fall over when detecting it. Example: if I
373 * have a number (-)0x8000 (G_MINSHORT), then my abs()<<1
374 * will be 0x10000; this is G_MAXUSHORT+1! So: if (<0) -1. */
375 guint64 unum = (num < 0 ? (-num - 1) << 1 : num << 1);
376 guint size = gst_ebml_write_get_uint_size (unum);
382 unum = 0x80 << (size - 1);
384 unum |= 0x80 << (size - 1);
388 gst_ebml_write_element_id (buf, id);
389 gst_ebml_write_element_size (buf, size);
390 gst_ebml_write_set_uint (buf, unum, size);
391 gst_ebml_write_element_push (ebml, buf);
395 gst_ebml_write_float (GstEbmlWrite * ebml, guint32 id, gdouble num)
397 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
400 GstBuffer *buf = gst_ebml_write_element_new (ebml, sizeof (num));
402 gst_ebml_write_element_id (buf, id);
403 gst_ebml_write_element_size (buf, 8);
404 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
405 for (n = 0; n < 8; n++)
406 GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf)] = ((guint8 *) & num)[7 - n];
407 GST_BUFFER_SIZE (buf) += 8;
409 gst_ebml_write_element_data (buf, (guint8 *) & num, 8);
411 gst_ebml_write_element_push (ebml, buf);
415 gst_ebml_write_ascii (GstEbmlWrite * ebml, guint32 id, const gchar * str)
417 gint len = strlen (str) + 1; /* add trailing '\0' */
418 GstBuffer *buf = gst_ebml_write_element_new (ebml, len);
420 gst_ebml_write_element_id (buf, id);
421 gst_ebml_write_element_size (buf, len);
422 gst_ebml_write_element_data (buf, (guint8 *) str, len);
423 gst_ebml_write_element_push (ebml, buf);
427 gst_ebml_write_utf8 (GstEbmlWrite * ebml, guint32 id, const gchar * str)
429 gst_ebml_write_ascii (ebml, id, str);
433 gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date)
435 gst_ebml_write_sint (ebml, id, date);
439 * Master writing is annoying. We use a size marker of
440 * the max. allowed length, so that we can later fill it
445 gst_ebml_write_master_start (GstEbmlWrite * ebml, guint32 id)
447 guint64 pos = ebml->pos, t;
448 GstBuffer *buf = gst_ebml_write_element_new (ebml, 0);
450 t = GST_BUFFER_SIZE (buf);
451 gst_ebml_write_element_id (buf, id);
452 pos += GST_BUFFER_SIZE (buf) - t;
453 gst_ebml_write_element_size (buf, -1);
454 gst_ebml_write_element_push (ebml, buf);
460 gst_ebml_write_master_finish (GstEbmlWrite * ebml, guint64 startpos)
462 guint64 pos = ebml->pos;
465 gst_ebml_write_seek (ebml, startpos);
466 buf = gst_ebml_write_element_new (ebml, 0);
467 startpos = GUINT64_TO_BE ((1LLU << 56) | (pos - startpos - 8));
468 memcpy (GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf),
469 (guint8 *) & startpos, 8);
470 GST_BUFFER_SIZE (buf) += 8;
471 gst_ebml_write_element_push (ebml, buf);
472 gst_ebml_write_seek (ebml, pos);
476 gst_ebml_write_binary (GstEbmlWrite * ebml,
477 guint32 id, guint8 * binary, guint64 length)
479 GstBuffer *buf = gst_ebml_write_element_new (ebml, length);
481 gst_ebml_write_element_id (buf, id);
482 gst_ebml_write_element_size (buf, length);
483 gst_ebml_write_element_data (buf, binary, length);
484 gst_ebml_write_element_push (ebml, buf);
488 * For things like video frames and audio samples,
489 * you want to use this function, as it doesn't have
490 * the overhead of memcpy() that other functions
491 * such as write_binary() do have.
495 gst_ebml_write_buffer_header (GstEbmlWrite * ebml, guint32 id, guint64 length)
497 GstBuffer *buf = gst_ebml_write_element_new (ebml, 0);
499 gst_ebml_write_element_id (buf, id);
500 gst_ebml_write_element_size (buf, length);
501 gst_ebml_write_element_push (ebml, buf);
505 gst_ebml_write_buffer (GstEbmlWrite * ebml, GstBuffer * data)
507 gst_ebml_write_element_push (ebml, data);
511 * When replacing a uint, we assume that it is *always*
512 * 8-byte, since that's the safest guess we can do. This
513 * is just for simplicity.
515 * FIXME: this function needs to be replaced with something
516 * proper. This is a crude hack.
520 gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
522 guint64 oldpos = ebml->pos;
523 GstBuffer *buf = gst_buffer_new_and_alloc (8);
525 gst_ebml_write_seek (ebml, pos);
526 GST_BUFFER_SIZE (buf) = 0;
527 gst_ebml_write_set_uint (buf, num, 8);
528 gst_ebml_write_element_push (ebml, buf);
529 gst_ebml_write_seek (ebml, oldpos);
537 gst_ebml_write_header (GstEbmlWrite * ebml, gchar * doctype, guint version)
541 /* write the basic EBML header */
542 gst_ebml_write_set_cache (ebml, 0x40);
543 pos = gst_ebml_write_master_start (ebml, GST_EBML_ID_HEADER);
544 #if (GST_EBML_VERSION != 1)
545 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLVERSION, GST_EBML_VERSION);
546 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLREADVERSION, GST_EBML_VERSION);
549 /* we don't write these until they're "non-default" (never!) */
550 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXIDLENGTH, sizeof (guint32));
551 gst_ebml_write_uint (ebml, GST_EBML_ID_EBMLMAXSIZELENGTH, sizeof (guint64));
553 gst_ebml_write_ascii (ebml, GST_EBML_ID_DOCTYPE, doctype);
554 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEVERSION, version);
555 gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
556 gst_ebml_write_master_finish (ebml, pos);
557 gst_ebml_write_flush_cache (ebml);