File: | build-analysis/../src/plugins/asf/libasf/data.c |
Warning: | line 74, column 2 Value stored to 'data' is never read |
1 | /* libasf - An Advanced Systems Format media file parser |
2 | * Copyright (C) 2006-2010 Juho Vähä-Herttua |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library; if not, write to the Free Software |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ |
18 | |
19 | #include <stdlib.h> |
20 | #include <string.h> |
21 | |
22 | #include "asfint.h" |
23 | #include "byteio.h" |
24 | #include "data.h" |
25 | #include "parse.h" |
26 | #include "debug.h" |
27 | |
28 | static int |
29 | asf_data_read_packet_fields(asf_packet_t *packet, uint8_t flags, |
30 | uint8_t *data, uint32_t len) |
31 | { |
32 | uint8_t datalen; |
33 | |
34 | datalen = GETLEN2b((flags >> 1) & 0x03)((((flags >> 1) & 0x03) == 0x03) ? 4 : (flags >> 1) & 0x03) + |
35 | GETLEN2b((flags >> 3) & 0x03)((((flags >> 3) & 0x03) == 0x03) ? 4 : (flags >> 3) & 0x03) + |
36 | GETLEN2b((flags >> 5) & 0x03)((((flags >> 5) & 0x03) == 0x03) ? 4 : (flags >> 5) & 0x03) + 6; |
37 | |
38 | if (datalen > len) { |
39 | return ASF_ERROR_INVALID_LENGTH; |
40 | } |
41 | |
42 | packet->length = GETVALUE2b((flags >> 5) & 0x03, data)((((flags >> 5) & 0x03) != 0x03) ? (((flags >> 5) & 0x03) != 0x02) ? (((flags >> 5) & 0x03) != 0x01) ? 0 : *((uint8_t *)data) : GetWLE(data) : GetDWLE(data )); |
43 | data += GETLEN2b((flags >> 5) & 0x03)((((flags >> 5) & 0x03) == 0x03) ? 4 : (flags >> 5) & 0x03); |
44 | packet->sequence = GETVALUE2b((flags >> 1) & 0x03, data)((((flags >> 1) & 0x03) != 0x03) ? (((flags >> 1) & 0x03) != 0x02) ? (((flags >> 1) & 0x03) != 0x01) ? 0 : *((uint8_t *)data) : GetWLE(data) : GetDWLE(data )); |
45 | data += GETLEN2b((flags >> 1) & 0x03)((((flags >> 1) & 0x03) == 0x03) ? 4 : (flags >> 1) & 0x03); |
46 | packet->padding_length = GETVALUE2b((flags >> 3) & 0x03, data)((((flags >> 3) & 0x03) != 0x03) ? (((flags >> 3) & 0x03) != 0x02) ? (((flags >> 3) & 0x03) != 0x01) ? 0 : *((uint8_t *)data) : GetWLE(data) : GetDWLE(data )); |
47 | data += GETLEN2b((flags >> 3) & 0x03)((((flags >> 3) & 0x03) == 0x03) ? 4 : (flags >> 3) & 0x03); |
48 | packet->send_time = GetDWLE(data); |
49 | data += 4; |
50 | packet->duration = GetWLE(data); |
51 | data += 2; |
52 | |
53 | return datalen; |
54 | } |
55 | |
56 | static int |
57 | asf_data_read_payload_fields(asf_payload_t *payload, uint8_t flags, uint8_t *data, int size) |
58 | { |
59 | uint8_t datalen; |
60 | |
61 | datalen = GETLEN2b(flags & 0x03)(((flags & 0x03) == 0x03) ? 4 : flags & 0x03) + |
62 | GETLEN2b((flags >> 2) & 0x03)((((flags >> 2) & 0x03) == 0x03) ? 4 : (flags >> 2) & 0x03) + |
63 | GETLEN2b((flags >> 4) & 0x03)((((flags >> 4) & 0x03) == 0x03) ? 4 : (flags >> 4) & 0x03); |
64 | |
65 | if (datalen > size) { |
66 | return ASF_ERROR_INVALID_LENGTH; |
67 | } |
68 | |
69 | payload->media_object_number = GETVALUE2b((flags >> 4) & 0x03, data)((((flags >> 4) & 0x03) != 0x03) ? (((flags >> 4) & 0x03) != 0x02) ? (((flags >> 4) & 0x03) != 0x01) ? 0 : *((uint8_t *)data) : GetWLE(data) : GetDWLE(data )); |
70 | data += GETLEN2b((flags >> 4) & 0x03)((((flags >> 4) & 0x03) == 0x03) ? 4 : (flags >> 4) & 0x03); |
71 | payload->media_object_offset = GETVALUE2b((flags >> 2) & 0x03, data)((((flags >> 2) & 0x03) != 0x03) ? (((flags >> 2) & 0x03) != 0x02) ? (((flags >> 2) & 0x03) != 0x01) ? 0 : *((uint8_t *)data) : GetWLE(data) : GetDWLE(data )); |
72 | data += GETLEN2b((flags >> 2) & 0x03)((((flags >> 2) & 0x03) == 0x03) ? 4 : (flags >> 2) & 0x03); |
73 | payload->replicated_length = GETVALUE2b(flags & 0x03, data)(((flags & 0x03) != 0x03) ? ((flags & 0x03) != 0x02) ? ((flags & 0x03) != 0x01) ? 0 : *((uint8_t *)data) : GetWLE (data) : GetDWLE(data)); |
74 | data += GETLEN2b(flags & 0x03)(((flags & 0x03) == 0x03) ? 4 : flags & 0x03); |
Value stored to 'data' is never read | |
75 | |
76 | return datalen; |
77 | } |
78 | |
79 | static int |
80 | asf_data_read_payloads(asf_packet_t *packet, |
81 | uint64_t preroll, |
82 | uint8_t multiple, |
83 | uint8_t flags, |
84 | uint8_t *data, |
85 | uint32_t datalen) |
86 | { |
87 | asf_payload_t pl; |
88 | uint32_t skip; |
89 | int i, tmp; |
90 | |
91 | skip = 0, i = 0; |
92 | while (i < packet->payload_count) { |
93 | uint8_t pts_delta = 0; |
94 | int compressed = 0; |
95 | |
96 | if (skip+1 > datalen) { |
97 | return ASF_ERROR_INVALID_LENGTH; |
98 | } |
99 | pl.stream_number = data[skip] & 0x7f; |
100 | pl.key_frame = !!(data[skip] & 0x80); |
101 | skip++; |
102 | |
103 | tmp = asf_data_read_payload_fields(&pl, flags, data + skip, datalen - skip); |
104 | if (tmp < 0) { |
105 | return tmp; |
106 | } |
107 | skip += tmp; |
108 | |
109 | if (pl.replicated_length > 1) { |
110 | if (pl.replicated_length < 8 || pl.replicated_length + skip > datalen) { |
111 | /* not enough data */ |
112 | return ASF_ERROR_INVALID_LENGTH; |
113 | } |
114 | pl.replicated_data = data + skip; |
115 | skip += pl.replicated_length; |
116 | |
117 | pl.pts = GetDWLE(pl.replicated_data + 4); |
118 | } else if (pl.replicated_length == 1) { |
119 | if (skip+1 > datalen) { |
120 | /* not enough data */ |
121 | return ASF_ERROR_INVALID_LENGTH; |
122 | } |
123 | |
124 | /* in compressed payload object offset is actually pts */ |
125 | pl.pts = pl.media_object_offset; |
126 | pl.media_object_offset = 0; |
127 | |
128 | pl.replicated_length = 0; |
129 | pl.replicated_data = NULL((void*)0); |
130 | |
131 | pts_delta = data[skip]; |
132 | skip++; |
133 | compressed = 1; |
134 | } else { |
135 | pl.pts = packet->send_time; |
136 | pl.replicated_data = NULL((void*)0); |
137 | } |
138 | |
139 | /* substract preroll value from pts since it's counted in */ |
140 | if (pl.pts > preroll) { |
141 | pl.pts -= preroll; |
142 | } else { |
143 | pl.pts = 0; |
144 | } |
145 | |
146 | if (multiple) { |
147 | if (skip + 2 > datalen) { |
148 | /* not enough data */ |
149 | return ASF_ERROR_INVALID_LENGTH; |
150 | } |
151 | pl.datalen = GetWLE(data + skip); |
152 | skip += 2; |
153 | } else { |
154 | pl.datalen = datalen - skip; |
155 | } |
156 | |
157 | if (compressed) { |
158 | uint32_t start = skip, used = 0; |
159 | int payloads, idx; |
160 | |
161 | /* count how many compressed payloads this payload includes */ |
162 | for (payloads=0; used < pl.datalen; payloads++) { |
163 | used += 1 + data[start + used]; |
164 | } |
165 | |
166 | if (used != pl.datalen) { |
167 | /* invalid compressed data size */ |
168 | return ASF_ERROR_INVALID_LENGTH; |
169 | } |
170 | |
171 | /* add additional payloads excluding the already allocated one */ |
172 | packet->payload_count += payloads - 1; |
173 | if (packet->payload_count > packet->payloads_size) { |
174 | void *tempptr; |
175 | |
176 | tempptr = realloc(packet->payloads, |
177 | packet->payload_count * sizeof(asf_payload_t)); |
178 | if (!tempptr) { |
179 | return ASF_ERROR_OUTOFMEM; |
180 | } |
181 | packet->payloads = tempptr; |
182 | packet->payloads_size = packet->payload_count; |
183 | } |
184 | |
185 | for (idx = 0; idx < payloads; idx++) { |
186 | pl.datalen = data[skip]; |
187 | skip++; |
188 | |
189 | /* Set data correctly */ |
190 | pl.data = data + skip; |
191 | skip += pl.datalen; |
192 | |
193 | /* Copy the final payload and update the PTS */ |
194 | memcpy(&packet->payloads[i], &pl, sizeof(asf_payload_t)); |
195 | packet->payloads[i].pts = pl.pts + idx * pts_delta; |
196 | i++; |
197 | |
198 | debug_printf("payload(%d/%d) stream: %d, key frame: %d, object: %d, offset: %d, pts: %d, datalen: %d", |
199 | i, packet->payload_count, pl.stream_number, (int) pl.key_frame, pl.media_object_number, |
200 | pl.media_object_offset, pl.pts + idx * pts_delta, pl.datalen); |
201 | } |
202 | } else { |
203 | pl.data = data + skip; |
204 | memcpy(&packet->payloads[i], &pl, sizeof(asf_payload_t)); |
205 | |
206 | /* update the skipped data amount and payload index */ |
207 | skip += pl.datalen; |
208 | i++; |
209 | |
210 | debug_printf("payload(%d/%d) stream: %d, key frame: %d, object: %d, offset: %d, pts: %d, datalen: %d", |
211 | i, packet->payload_count, pl.stream_number, (int) pl.key_frame, pl.media_object_number, |
212 | pl.media_object_offset, pl.pts, pl.datalen); |
213 | } |
214 | } |
215 | |
216 | return skip; |
217 | } |
218 | |
219 | void |
220 | asf_data_init_packet(asf_packet_t *packet) |
221 | { |
222 | packet->ec_length = 0; |
223 | packet->ec_data = NULL((void*)0); |
224 | |
225 | packet->length = 0; |
226 | packet->padding_length = 0; |
227 | packet->send_time = 0; |
228 | packet->duration = 0; |
229 | |
230 | packet->payload_count = 0; |
231 | packet->payloads = NULL((void*)0); |
232 | packet->payloads_size = 0; |
233 | |
234 | packet->payload_data_len = 0; |
235 | packet->payload_data = NULL((void*)0); |
236 | |
237 | packet->data = NULL((void*)0); |
238 | packet->data_size = 0; |
239 | } |
240 | |
241 | int |
242 | asf_data_get_packet(asf_packet_t *packet, asf_file_t *file) |
243 | { |
244 | asf_iostream_t *iostream; |
245 | uint32_t read = 0; |
246 | int packet_flags, packet_property; |
247 | void *tmpptr; |
248 | int tmp; |
249 | |
250 | iostream = &file->iostream; |
251 | if (file->packet_size == 0) { |
252 | return ASF_ERROR_INVALID_LENGTH; |
253 | } |
254 | |
255 | /* If the internal data is not allocated, allocate it */ |
256 | if (packet->data_size < file->packet_size) { |
257 | tmpptr = realloc(packet->data, file->packet_size); |
258 | if (!tmpptr) { |
259 | return ASF_ERROR_OUTOFMEM; |
260 | } |
261 | packet->data = tmpptr; |
262 | packet->data_size = file->packet_size; |
263 | } |
264 | |
265 | tmp = asf_byteio_read(iostream, packet->data, file->packet_size); |
266 | if (tmp < 0) { |
267 | /* Error reading packet data */ |
268 | return tmp; |
269 | } |
270 | |
271 | tmp = packet->data[read++]; |
272 | if (tmp & 0x80) { |
273 | uint8_t opaque_data, ec_length_type; |
274 | |
275 | packet->ec_length = tmp & 0x0f; |
276 | opaque_data = (tmp >> 4) & 0x01; |
277 | ec_length_type = (tmp >> 5) & 0x03; |
278 | |
279 | if (ec_length_type != 0x00 || |
280 | opaque_data != 0 || |
281 | packet->ec_length != 0x02) { |
282 | /* incorrect error correction flags */ |
283 | return ASF_ERROR_INVALID_VALUE; |
284 | } |
285 | |
286 | if (read+packet->ec_length > file->packet_size) { |
287 | return ASF_ERROR_INVALID_LENGTH; |
288 | } |
289 | packet->ec_data = &packet->data[read]; |
290 | read += packet->ec_length; |
291 | } else { |
292 | packet->ec_length = 0; |
293 | packet->ec_data = NULL((void*)0); |
294 | } |
295 | |
296 | if (read+2 > file->packet_size) { |
297 | return ASF_ERROR_INVALID_LENGTH; |
298 | } |
299 | packet_flags = packet->data[read++]; |
300 | packet_property = packet->data[read++]; |
301 | |
302 | tmp = asf_data_read_packet_fields(packet, packet_flags, |
303 | packet->data + read, |
304 | file->packet_size - read); |
305 | if (tmp < 0) { |
306 | return tmp; |
307 | } |
308 | read += tmp; |
309 | |
310 | /* this is really idiotic, packet length can (and often will) be |
311 | * undefined and we just have to use the header packet size as the size |
312 | * value */ |
313 | if (((packet_flags >> 5) & 0x03) == 0) { |
314 | packet->length = file->packet_size; |
315 | } |
316 | |
317 | /* this is also really idiotic, if packet length is smaller than packet |
318 | * size, we need to manually add the additional bytes into padding length |
319 | * because the padding bytes only count up to packet length value */ |
320 | if (packet->length < file->packet_size) { |
321 | packet->padding_length += file->packet_size - packet->length; |
322 | packet->length = file->packet_size; |
323 | } |
324 | |
325 | if (packet->length != file->packet_size) { |
326 | /* packet with invalid length value */ |
327 | return ASF_ERROR_INVALID_LENGTH; |
328 | } |
329 | |
330 | /* check if we have multiple payloads */ |
331 | if (packet_flags & 0x01) { |
332 | int payload_length_type; |
333 | |
334 | if (read+1 > packet->length) { |
335 | return ASF_ERROR_INVALID_LENGTH; |
336 | } |
337 | tmp = packet->data[read++]; |
338 | |
339 | packet->payload_count = tmp & 0x3f; |
340 | payload_length_type = (tmp >> 6) & 0x03; |
341 | |
342 | if (packet->payload_count == 0) { |
343 | /* there should always be at least one payload */ |
344 | return ASF_ERROR_INVALID_VALUE; |
345 | } |
346 | |
347 | if (payload_length_type != 0x02) { |
348 | /* in multiple payloads datalen should always be a word */ |
349 | return ASF_ERROR_INVALID_VALUE; |
350 | } |
351 | } else { |
352 | packet->payload_count = 1; |
353 | } |
354 | packet->payload_data_len = packet->length - read; |
355 | |
356 | if (packet->payload_count > packet->payloads_size) { |
357 | tmpptr = realloc(packet->payloads, |
358 | packet->payload_count * sizeof(asf_payload_t)); |
359 | if (!tmpptr) { |
360 | return ASF_ERROR_OUTOFMEM; |
361 | } |
362 | packet->payloads = tmpptr; |
363 | packet->payloads_size = packet->payload_count; |
364 | } |
365 | |
366 | packet->payload_data = &packet->data[read]; |
367 | read += packet->payload_data_len; |
368 | |
369 | /* The return value will be consumed bytes, not including the padding */ |
370 | tmp = asf_data_read_payloads(packet, file->preroll, packet_flags & 0x01, |
371 | packet_property, packet->payload_data, |
372 | packet->payload_data_len - packet->padding_length); |
373 | if (tmp < 0) { |
374 | return tmp; |
375 | } |
376 | |
377 | debug_printf("packet read %d bytes, eclen: %d, length: %d, padding: %d, time %d, duration: %d, payloads: %d", |
378 | read, packet->ec_length, packet->length, packet->padding_length, packet->send_time, |
379 | packet->duration, packet->payload_count); |
380 | |
381 | return read; |
382 | } |
383 | |
384 | void |
385 | asf_data_free_packet(asf_packet_t *packet) |
386 | { |
387 | if (!packet) |
388 | return; |
389 | |
390 | free(packet->payloads); |
391 | free(packet->data); |
392 | |
393 | packet->ec_data = NULL((void*)0); |
394 | packet->payloads = NULL((void*)0); |
395 | packet->payload_data = NULL((void*)0); |
396 | packet->data = NULL((void*)0); |
397 | } |