Home | History | Annotate | Download | only in libmkv
      1 /*
      2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 #include "EbmlWriter.h"
     11 #include <stdlib.h>
     12 #include <wchar.h>
     13 #include <string.h>
     14 #include <limits.h>
     15 #if defined(_MSC_VER)
     16 #define LITERALU64(n) n
     17 #else
     18 #define LITERALU64(n) n##LLU
     19 #endif
     20 
     21 void Ebml_WriteLen(EbmlGlobal *glob, int64_t val) {
     22   /* TODO check and make sure we are not > than 0x0100000000000000LLU */
     23   unsigned char size = 8; /* size in bytes to output */
     24 
     25   /* mask to compare for byte size */
     26   int64_t minVal = 0xff;
     27 
     28   for (size = 1; size < 8; size ++) {
     29     if (val < minVal)
     30       break;
     31 
     32     minVal = (minVal << 7);
     33   }
     34 
     35   val |= (((uint64_t)0x80) << ((size - 1) * 7));
     36 
     37   Ebml_Serialize(glob, (void *) &val, sizeof(val), size);
     38 }
     39 
     40 void Ebml_WriteString(EbmlGlobal *glob, const char *str) {
     41   const size_t size_ = strlen(str);
     42   const uint64_t  size = size_;
     43   Ebml_WriteLen(glob, size);
     44   /* TODO: it's not clear from the spec whether the nul terminator
     45    * should be serialized too.  For now we omit the null terminator.
     46    */
     47   Ebml_Write(glob, str, (unsigned long)size);
     48 }
     49 
     50 void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr) {
     51   const size_t strlen = wcslen(wstr);
     52 
     53   /* TODO: it's not clear from the spec whether the nul terminator
     54    * should be serialized too.  For now we include it.
     55    */
     56   const uint64_t  size = strlen;
     57 
     58   Ebml_WriteLen(glob, size);
     59   Ebml_Write(glob, wstr, (unsigned long)size);
     60 }
     61 
     62 void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id) {
     63   int len;
     64 
     65   if (class_id >= 0x01000000)
     66     len = 4;
     67   else if (class_id >= 0x00010000)
     68     len = 3;
     69   else if (class_id >= 0x00000100)
     70     len = 2;
     71   else
     72     len = 1;
     73 
     74   Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len);
     75 }
     76 
     77 void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) {
     78   unsigned char sizeSerialized = 8 | 0x80;
     79   Ebml_WriteID(glob, class_id);
     80   Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
     81   Ebml_Serialize(glob, &ui, sizeof(ui), 8);
     82 }
     83 
     84 void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui) {
     85   unsigned char size = 8; /* size in bytes to output */
     86   unsigned char sizeSerialized = 0;
     87   unsigned long minVal;
     88 
     89   Ebml_WriteID(glob, class_id);
     90   minVal = 0x7fLU; /* mask to compare for byte size */
     91 
     92   for (size = 1; size < 4; size ++) {
     93     if (ui < minVal) {
     94       break;
     95     }
     96 
     97     minVal <<= 7;
     98   }
     99 
    100   sizeSerialized = 0x80 | size;
    101   Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
    102   Ebml_Serialize(glob, &ui, sizeof(ui), size);
    103 }
    104 /* TODO: perhaps this is a poor name for this id serializer helper function */
    105 void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long bin) {
    106   int size;
    107   for (size = 4; size > 1; size--) {
    108     if (bin & (unsigned int)0x000000ff << ((size - 1) * 8))
    109       break;
    110   }
    111   Ebml_WriteID(glob, class_id);
    112   Ebml_WriteLen(glob, size);
    113   Ebml_WriteID(glob, bin);
    114 }
    115 
    116 void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d) {
    117   unsigned char len = 0x88;
    118 
    119   Ebml_WriteID(glob, class_id);
    120   Ebml_Serialize(glob, &len, sizeof(len), 1);
    121   Ebml_Serialize(glob,  &d, sizeof(d), 8);
    122 }
    123 
    124 void Ebml_WriteSigned16(EbmlGlobal *glob, short val) {
    125   signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8;
    126   Ebml_Serialize(glob, &out, sizeof(out), 3);
    127 }
    128 
    129 void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s) {
    130   Ebml_WriteID(glob, class_id);
    131   Ebml_WriteString(glob, s);
    132 }
    133 
    134 void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s) {
    135   Ebml_WriteID(glob,  class_id);
    136   Ebml_WriteUTF8(glob,  s);
    137 }
    138 
    139 void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length) {
    140   Ebml_WriteID(glob, class_id);
    141   Ebml_WriteLen(glob, data_length);
    142   Ebml_Write(glob,  data, data_length);
    143 }
    144 
    145 void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize) {
    146   unsigned char tmp = 0;
    147   unsigned long i = 0;
    148 
    149   Ebml_WriteID(glob, 0xEC);
    150   Ebml_WriteLen(glob, vSize);
    151 
    152   for (i = 0; i < vSize; i++) {
    153     Ebml_Write(glob, &tmp, 1);
    154   }
    155 }
    156 
    157 /* TODO Serialize Date */
    158