1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar
7 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
25 #define XIPH_MAX_HEADER_COUNT (256)
27 /* Temp ffmpeg vorbis format */
28 static inline bool xiph_IsOldFormat( const void *extra
, unsigned int i_extra
)
30 if ( i_extra
>= 6 && GetWBE( extra
) == 30 )
36 static inline unsigned int xiph_CountHeaders( const void *extra
, unsigned int i_extra
)
38 const uint8_t *p_extra
= (uint8_t*) extra
;
39 if ( !i_extra
) return 0;
40 if ( xiph_IsOldFormat( extra
, i_extra
) )
42 /* Check headers count */
43 unsigned int overall_len
= 6;
44 for ( int i
=0; i
<3; i
++ )
46 uint16_t i_size
= GetWBE( extra
);
47 p_extra
+= 2 + i_size
;
48 if ( overall_len
> i_extra
- i_size
)
50 overall_len
+= i_size
;
60 static inline int xiph_SplitHeaders(unsigned packet_size
[], void * packet
[], unsigned *packet_count
,
61 unsigned extra_size
, const void *extra
)
63 const uint8_t *current
= (const uint8_t *)extra
;
64 const uint8_t *end
= ¤t
[extra_size
];
68 /* Parse the packet count and their sizes */
69 const unsigned count
= xiph_CountHeaders( current
++, extra_size
);
71 *packet_count
= count
;
73 if ( xiph_IsOldFormat( extra
, extra_size
) )
75 uint8_t *p_extra
= (uint8_t*) extra
;
76 unsigned int overall_len
= count
<< 1;
77 for ( unsigned int i
=0; i
< count
; i
++ ) {
78 packet_size
[i
] = GetWBE( p_extra
);
79 packet
[i
] = p_extra
+ 2;
80 p_extra
+= packet_size
[i
] + 2;
81 if (overall_len
> extra_size
- packet_size
[i
])
83 overall_len
+= packet_size
[i
];
89 for (unsigned i
= 0; i
< count
- 1; i
++) {
94 packet_size
[i
] += *current
;
95 if (*current
++ != 255)
98 size
+= packet_size
[i
];
100 if (end
- current
< size
)
102 packet_size
[count
- 1] = end
- current
- size
;
104 for (unsigned i
= 0; i
< count
; i
++)
105 if (packet_size
[i
] > 0) {
106 packet
[i
] = (void *) current
;
107 current
+= packet_size
[i
];
113 static inline int xiph_PackHeaders(int *extra_size
, void **extra
,
114 unsigned packet_size
[], const void *packet
[], unsigned packet_count
)
116 if (packet_count
<= 0 || packet_count
> XIPH_MAX_HEADER_COUNT
)
119 /* Compute the size needed for the whole extra data */
120 unsigned payload_size
= 0;
121 unsigned header_size
= 1;
122 for (unsigned i
= 0; i
< packet_count
; i
++) {
123 payload_size
+= packet_size
[i
];
124 if (i
< packet_count
- 1)
125 header_size
+= 1 + packet_size
[i
] / 255;
129 *extra_size
= header_size
+ payload_size
;
130 *extra
= malloc(*extra_size
);
134 /* Write the header */
135 uint8_t *current
= (uint8_t*)*extra
;
136 *current
++ = packet_count
- 1;
137 for (unsigned i
= 0; i
< packet_count
- 1; i
++) {
138 unsigned t
= packet_size
[i
];
150 /* Copy the payloads */
151 for (unsigned i
= 0; i
< packet_count
; i
++) {
152 if (packet_size
[i
] > 0) {
153 memcpy(current
, packet
[i
], packet_size
[i
]);
154 current
+= packet_size
[i
];
157 assert(current
== (uint8_t*)*extra
+ *extra_size
);
161 static inline int xiph_AppendHeaders(int *extra_size
, void **extra
,
162 unsigned size
, const void *data
)
164 unsigned packet_size
[XIPH_MAX_HEADER_COUNT
];
165 void *packet
[XIPH_MAX_HEADER_COUNT
];
167 if (*extra_size
> 0 && *extra
) {
168 if (xiph_SplitHeaders(packet_size
, packet
, &count
, *extra_size
, *extra
))
173 if (count
>= XIPH_MAX_HEADER_COUNT
)
178 packet_size
[count
] = size
;
179 packet
[count
] = (void*)data
;
180 if (xiph_PackHeaders(extra_size
, extra
, packet_size
,
181 (const void **)packet
, count
+ 1)) {
188 if (*extra_size
<= 0)