EbmlWriter.c 4.33 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
10 11 12 13
#include "EbmlWriter.h"
#include <stdlib.h>
#include <wchar.h>
#include <string.h>
14
#include <limits.h>
15 16 17 18 19
#if defined(_MSC_VER)
#define LITERALU64(n) n
#else
#define LITERALU64(n) n##LLU
#endif
20

21 22 23
void Ebml_WriteLen(EbmlGlobal *glob, int64_t val) {
  /* TODO check and make sure we are not > than 0x0100000000000000LLU */
  unsigned char size = 8; /* size in bytes to output */
24

25 26
  /* mask to compare for byte size */
  int64_t minVal = 0xff;
John Koleszar's avatar
John Koleszar committed
27 28 29 30

  for (size = 1; size < 8; size ++) {
    if (val < minVal)
      break;
31

John Koleszar's avatar
John Koleszar committed
32 33
    minVal = (minVal << 7);
  }
34

35
  val |= (((uint64_t)0x80) << ((size - 1) * 7));
John Koleszar's avatar
John Koleszar committed
36 37

  Ebml_Serialize(glob, (void *) &val, sizeof(val), size);
38 39
}

John Koleszar's avatar
John Koleszar committed
40 41
void Ebml_WriteString(EbmlGlobal *glob, const char *str) {
  const size_t size_ = strlen(str);
42
  const uint64_t  size = size_;
John Koleszar's avatar
John Koleszar committed
43
  Ebml_WriteLen(glob, size);
44 45 46 47
  /* TODO: it's not clear from the spec whether the nul terminator
   * should be serialized too.  For now we omit the null terminator.
   */
  Ebml_Write(glob, str, (unsigned long)size);
48 49
}

John Koleszar's avatar
John Koleszar committed
50 51
void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr) {
  const size_t strlen = wcslen(wstr);
52

53 54 55 56
  /* TODO: it's not clear from the spec whether the nul terminator
   * should be serialized too.  For now we include it.
   */
  const uint64_t  size = strlen;
57

John Koleszar's avatar
John Koleszar committed
58
  Ebml_WriteLen(glob, size);
59
  Ebml_Write(glob, wstr, (unsigned long)size);
60 61
}

John Koleszar's avatar
John Koleszar committed
62 63
void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id) {
  int len;
64

John Koleszar's avatar
John Koleszar committed
65 66 67 68 69 70 71 72
  if (class_id >= 0x01000000)
    len = 4;
  else if (class_id >= 0x00010000)
    len = 3;
  else if (class_id >= 0x00000100)
    len = 2;
  else
    len = 1;
73

John Koleszar's avatar
John Koleszar committed
74
  Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len);
75
}
76

John Koleszar's avatar
John Koleszar committed
77 78 79 80 81
void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) {
  unsigned char sizeSerialized = 8 | 0x80;
  Ebml_WriteID(glob, class_id);
  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
  Ebml_Serialize(glob, &ui, sizeof(ui), 8);
82 83
}

John Koleszar's avatar
John Koleszar committed
84
void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui) {
85
  unsigned char size = 8; /* size in bytes to output */
John Koleszar's avatar
John Koleszar committed
86 87
  unsigned char sizeSerialized = 0;
  unsigned long minVal;
88

John Koleszar's avatar
John Koleszar committed
89
  Ebml_WriteID(glob, class_id);
90
  minVal = 0x7fLU; /* mask to compare for byte size */
91

John Koleszar's avatar
John Koleszar committed
92 93 94
  for (size = 1; size < 4; size ++) {
    if (ui < minVal) {
      break;
95 96
    }

John Koleszar's avatar
John Koleszar committed
97 98 99 100 101 102
    minVal <<= 7;
  }

  sizeSerialized = 0x80 | size;
  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
  Ebml_Serialize(glob, &ui, sizeof(ui), size);
103
}
104
/* TODO: perhaps this is a poor name for this id serializer helper function */
John Koleszar's avatar
John Koleszar committed
105 106 107 108 109 110 111 112 113
void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long bin) {
  int size;
  for (size = 4; size > 1; size--) {
    if (bin & 0x000000ff << ((size - 1) * 8))
      break;
  }
  Ebml_WriteID(glob, class_id);
  Ebml_WriteLen(glob, size);
  Ebml_WriteID(glob, bin);
114 115
}

John Koleszar's avatar
John Koleszar committed
116 117
void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d) {
  unsigned char len = 0x88;
118

John Koleszar's avatar
John Koleszar committed
119 120 121
  Ebml_WriteID(glob, class_id);
  Ebml_Serialize(glob, &len, sizeof(len), 1);
  Ebml_Serialize(glob,  &d, sizeof(d), 8);
122 123
}

John Koleszar's avatar
John Koleszar committed
124 125 126
void Ebml_WriteSigned16(EbmlGlobal *glob, short val) {
  signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8;
  Ebml_Serialize(glob, &out, sizeof(out), 3);
127 128
}

John Koleszar's avatar
John Koleszar committed
129 130 131
void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s) {
  Ebml_WriteID(glob, class_id);
  Ebml_WriteString(glob, s);
132 133
}

John Koleszar's avatar
John Koleszar committed
134 135 136
void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s) {
  Ebml_WriteID(glob,  class_id);
  Ebml_WriteUTF8(glob,  s);
137 138
}

John Koleszar's avatar
John Koleszar committed
139 140 141 142
void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length) {
  Ebml_WriteID(glob, class_id);
  Ebml_WriteLen(glob, data_length);
  Ebml_Write(glob,  data, data_length);
143 144
}

John Koleszar's avatar
John Koleszar committed
145 146 147
void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize) {
  unsigned char tmp = 0;
  unsigned long i = 0;
148

John Koleszar's avatar
John Koleszar committed
149 150
  Ebml_WriteID(glob, 0xEC);
  Ebml_WriteLen(glob, vSize);
151

John Koleszar's avatar
John Koleszar committed
152 153 154
  for (i = 0; i < vSize; i++) {
    Ebml_Write(glob, &tmp, 1);
  }
155 156
}

157
/* TODO Serialize Date */