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 28static int 29asf_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) + 35 GETLEN2b((flags >> 3) & 0x03) + 36 GETLEN2b((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); 43 data += GETLEN2b((flags >> 5) & 0x03); 44 packet->sequence = GETVALUE2b((flags >> 1) & 0x03, data); 45 data += GETLEN2b((flags >> 1) & 0x03); 46 packet->padding_length = GETVALUE2b((flags >> 3) & 0x03, data); 47 data += GETLEN2b((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 56static int 57asf_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) + 62 GETLEN2b((flags >> 2) & 0x03) + 63 GETLEN2b((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); 70 data += GETLEN2b((flags >> 4) & 0x03); 71 payload->media_object_offset = GETVALUE2b((flags >> 2) & 0x03, data); 72 data += GETLEN2b((flags >> 2) & 0x03); 73 payload->replicated_length = GETVALUE2b(flags & 0x03, data); 74 data += GETLEN2b(flags & 0x03); 75 76 return datalen; 77} 78 79static int 80asf_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; 130 131 pts_delta = data[skip]; 132 skip++; 133 compressed = 1; 134 } else { 135 pl.pts = packet->send_time; 136 pl.replicated_data = NULL; 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 219void 220asf_data_init_packet(asf_packet_t *packet) 221{ 222 packet->ec_length = 0; 223 packet->ec_data = NULL; 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; 232 packet->payloads_size = 0; 233 234 packet->payload_data_len = 0; 235 packet->payload_data = NULL; 236 237 packet->data = NULL; 238 packet->data_size = 0; 239} 240 241int 242asf_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; 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 384void 385asf_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; 394 packet->payloads = NULL; 395 packet->payload_data = NULL; 396 packet->data = NULL; 397} 398