1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar
6 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
25 #define XIPH_MAX_HEADER_COUNT (256)
27 /* Temp ffmpeg vorbis format */
28 static inline bool xiph_IsLavcFormat(const void *extra
, unsigned i_extra
,
33 case VLC_CODEC_VORBIS
:
34 return i_extra
>= 6 && GetWBE(extra
) == 30;
35 case VLC_CODEC_THEORA
:
36 return i_extra
>= 6 && GetWBE(extra
) == 42;
42 static inline unsigned xiph_CountLavcHeaders(const void *p_extra
, unsigned i_extra
)
44 const uint8_t *p
= (const uint8_t*) p_extra
;
45 const uint8_t *p_end
= &p
[i_extra
];
46 /* Check headers count */
47 for (int i
=0; i
<3; i
++)
51 uint16_t i_size
= GetWBE(p
);
52 if(&p
[2U + i_size
] > p_end
)
59 static inline unsigned xiph_CountHeaders(const void *p_extra
, unsigned i_extra
)
61 const uint8_t *p
= (const uint8_t*) p_extra
;
64 /* First byte is headers count */
70 static inline unsigned xiph_CountUnknownHeaders(const void *p_extra
, unsigned i_extra
,
73 if (xiph_IsLavcFormat(p_extra
, i_extra
, i_codec
))
74 return xiph_CountLavcHeaders(p_extra
, i_extra
);
76 return xiph_CountHeaders(p_extra
, i_extra
);
79 static inline int xiph_SplitLavcHeaders(unsigned packet_size
[],
80 const void *packet
[], unsigned *packet_count
,
81 unsigned i_extra
, const void *p_extra
)
83 const uint8_t *current
= (const uint8_t *)p_extra
;
84 const uint8_t *end
= ¤t
[i_extra
];
87 /* Parse the packet count and their sizes */
88 const unsigned count
= xiph_CountLavcHeaders(current
, i_extra
);
92 *packet_count
= count
;
93 /* count is trusted here (xiph_CountHeaders) */
94 for (unsigned i
=0; i
< count
; i
++)
96 /* each payload is prefixed by word size */
97 packet_size
[i
] = GetWBE(current
);
98 if(¤t
[2U + packet_size
[i
]] > end
)
100 packet
[i
] = current
+ 2;
101 current
+= packet_size
[i
] + 2;
106 static inline int xiph_SplitHeaders(unsigned packet_size
[],
107 const void *packet
[], unsigned *packet_count
,
108 unsigned i_extra
, const void *p_extra
)
110 const uint8_t *current
= (const uint8_t *)p_extra
;
111 const uint8_t *end
= ¤t
[i_extra
];
115 /* Parse the packet count and their sizes */
116 const unsigned count
= xiph_CountHeaders(current
, i_extra
);
121 *packet_count
= count
;
123 /* - 1 byte (N-1) packets
124 * - N-1 variable length payload sizes
126 * - Nth packet (remaining) */
128 /* skip count byte header */
130 /* read sizes for N-1 packets */
131 unsigned total_payload_minus_last
= 0;
132 for (unsigned i
= 0; i
< count
- 1; i
++)
138 packet_size
[i
] += *current
;
139 if (*current
++ != 255)
142 if(UINT_MAX
- total_payload_minus_last
< packet_size
[i
])
144 total_payload_minus_last
+= packet_size
[i
];
146 if(current
+ total_payload_minus_last
> end
)
148 /* set pointers for N-1 packets */
149 for (unsigned i
= 0; i
< count
- 1; i
++)
152 current
+= packet_size
[i
];
154 /* Last packet is remaining size */
155 packet_size
[count
- 1] = end
- current
;
156 packet
[count
- 1] = current
;
161 static inline int xiph_PackHeaders(int *extra_size
, void **extra
,
162 unsigned packet_size
[],
163 const void *const packet
[],
164 unsigned packet_count
)
166 if (packet_count
<= 0 || packet_count
> XIPH_MAX_HEADER_COUNT
)
169 /* Compute the size needed for the whole extra data */
170 unsigned payload_size
= 0;
171 unsigned header_size
= 1;
172 for (unsigned i
= 0; i
< packet_count
; i
++) {
173 payload_size
+= packet_size
[i
];
174 if (i
< packet_count
- 1)
175 header_size
+= 1 + packet_size
[i
] / 255;
179 *extra_size
= header_size
+ payload_size
;
180 *extra
= malloc(*extra_size
);
184 /* Write the header */
185 uint8_t *current
= (uint8_t*)*extra
;
186 *current
++ = packet_count
- 1;
187 for (unsigned i
= 0; i
< packet_count
- 1; i
++) {
188 unsigned t
= packet_size
[i
];
200 /* Copy the payloads */
201 for (unsigned i
= 0; i
< packet_count
; i
++) {
202 if (packet_size
[i
] > 0) {
203 memcpy(current
, packet
[i
], packet_size
[i
]);
204 current
+= packet_size
[i
];
207 assert(current
== (uint8_t*)*extra
+ *extra_size
);
211 static inline int xiph_AppendHeaders(int *extra_size
, void **extra
,
212 unsigned size
, const void *data
)
214 unsigned packet_size
[XIPH_MAX_HEADER_COUNT
];
215 const void *packet
[XIPH_MAX_HEADER_COUNT
];
218 if (*extra_size
> 0 && *extra
) {
219 if (xiph_SplitHeaders(packet_size
, packet
, &count
, *extra_size
, *extra
))
224 if (count
>= XIPH_MAX_HEADER_COUNT
)
229 packet_size
[count
] = size
;
230 packet
[count
] = (void*)data
;
231 if (xiph_PackHeaders(extra_size
, extra
, packet_size
,
232 packet
, count
+ 1)) {
239 if (*extra_size
<= 0)