xiph.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <assert.h>
00025 #define XIPH_MAX_HEADER_COUNT (256)
00026
00027 static inline int xiph_SplitHeaders(unsigned packet_size[], void *packet[], unsigned *packet_count,
00028 unsigned extra_size, const void *extra)
00029 {
00030 const uint8_t *current = (const uint8_t*)extra;
00031 const uint8_t *end = ¤t[extra_size];
00032 if (extra_size < 1)
00033 return VLC_EGENERIC;
00034
00035
00036 const unsigned count = 1 + *current++;
00037 if (packet_count)
00038 *packet_count = count;
00039 unsigned size = 0;
00040 for (unsigned i = 0; i < count - 1; i++) {
00041 packet_size[i] = 0;
00042 for (;;) {
00043 if (current >= end)
00044 return VLC_EGENERIC;
00045 packet_size[i] += *current;
00046 if (*current++ != 255)
00047 break;
00048 }
00049 size += packet_size[i];
00050 }
00051 if (end - current < size)
00052 return VLC_EGENERIC;
00053 packet_size[count - 1] = end - current - size;
00054
00055
00056 for (unsigned i = 0; i < count; i++) {
00057 packet[i] = malloc(packet_size[i]);
00058 if (!packet[i]) {
00059 for (unsigned j = 0; j < i; j++)
00060 free(packet[j]);
00061 return VLC_ENOMEM;
00062 }
00063 if (packet_size[i] > 0) {
00064 memcpy(packet[i], current, packet_size[i]);
00065 current += packet_size[i];
00066 }
00067 }
00068 return VLC_SUCCESS;
00069 }
00070
00071 static inline int xiph_PackHeaders(int *extra_size, void **extra,
00072 unsigned packet_size[], void *packet[], unsigned packet_count )
00073 {
00074 if (packet_count <= 0 || packet_count > XIPH_MAX_HEADER_COUNT)
00075 return VLC_EGENERIC;
00076
00077
00078 unsigned payload_size = 0;
00079 unsigned header_size = 1;
00080 for (unsigned i = 0; i < packet_count; i++) {
00081 payload_size += packet_size[i];
00082 if (i < packet_count - 1)
00083 header_size += 1 + packet_size[i] / 255;
00084 }
00085
00086
00087 *extra_size = header_size + payload_size;
00088 *extra = malloc(*extra_size);
00089 if (*extra == NULL)
00090 return VLC_ENOMEM;
00091
00092
00093 uint8_t *current = (uint8_t*)*extra;
00094 *current++ = packet_count - 1;
00095 for (unsigned i = 0; i < packet_count - 1; i++) {
00096 unsigned t = packet_size[i];
00097 for (;;) {
00098 if (t >= 255) {
00099 *current++ = 255;
00100 t -= 255;
00101 } else {
00102 *current++ = t;
00103 break;
00104 }
00105 }
00106 }
00107
00108
00109 for (unsigned i = 0; i < packet_count; i++) {
00110 if (packet_size[i] > 0) {
00111 memcpy(current, packet[i], packet_size[i]);
00112 current += packet_size[i];
00113 }
00114 }
00115 assert(current == (uint8_t*)*extra + *extra_size);
00116 return VLC_SUCCESS;
00117 }
00118
00119 static inline int xiph_AppendHeaders(int *extra_size, void **extra,
00120 unsigned size, const void *data)
00121 {
00122 unsigned packet_size[XIPH_MAX_HEADER_COUNT];
00123 void *packet[XIPH_MAX_HEADER_COUNT];
00124 unsigned count;
00125 if (*extra_size > 0 && *extra) {
00126 if (xiph_SplitHeaders(packet_size, packet, &count, *extra_size, *extra))
00127 return VLC_EGENERIC;
00128 } else {
00129 count = 0;
00130 }
00131 if (count >= XIPH_MAX_HEADER_COUNT)
00132 return VLC_EGENERIC;
00133
00134 free(*extra);
00135
00136 packet_size[count] = size;
00137 packet[count] = (void*)data;
00138 if (xiph_PackHeaders(extra_size, extra, packet_size, packet, count + 1)) {
00139 *extra_size = 0;
00140 *extra = NULL;
00141 }
00142 for (unsigned i = 0; i < count; i++)
00143 free(packet[i]);
00144
00145 if (*extra_size <= 0)
00146 return VLC_EGENERIC;
00147 return VLC_SUCCESS;
00148 }
00149