1 /*
2 * Copyright (C) 2000-2018 the xine project
3 *
4 * This file is part of xine, a free video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * demultiplexer for asf streams
21 *
22 * based on ffmpeg's
23 * ASF compatible encoder and decoder.
24 * Copyright (c) 2000, 2001 Gerard Lantau.
25 *
26 * GUID list from avifile
27 * some other ideas from MPlayer
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #ifdef HAVE_ICONV
35 #include <iconv.h>
36 #endif
37
38 #include <string.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41
42
43 #define LOG_MODULE "asfheader"
44 #define LOG_VERBOSE
45 /*
46 #define LOG
47 */
48
49 #include <xine/xineutils.h>
50 #include "bswap.h"
51 #include "asfheader.h"
52
53 /* #define TEST_INTERNAL_ICONV */
54 #if !defined(HAVE_ICONV) || defined(TEST_INTERNAL_ICONV)
55
56 /* manual straightforward utf16 -> utf8 conversion */
57
58 # define iconv_open(TO, FROM) 0
59 # define iconv(CD, INBUF, INLEFT, OUTBUF, OUTLEFT) iconv_internal(INBUF, INLEFT, OUTBUF, OUTLEFT)
60 # define iconv_close(CD)
61 # ifdef ICONV_CONST
62 # undef ICONV_CONST
63 # endif
64 # define ICONV_CONST const
65
66 # if !defined(HAVE_ICONV)
67 typedef int iconv_t;
68 # endif
69
iconv_internal(const char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)70 static size_t iconv_internal (const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) {
71 const uint8_t *p = (const uint8_t *)*inbuf;
72 uint8_t *q = (uint8_t *)*outbuf;
73 uint32_t a = (*inbytesleft) >> 1;
74 uint32_t b = *outbytesleft;
75 while (a) {
76 uint32_t z = _X_LE_16 (p);
77 if (z & 0xff80) {
78 if (z & 0xf800) {
79 /* 1110xxxx 10xxxxxx 10xxxxxx */
80 if (b < 3)
81 break;
82 *q++ = 0xe0 | (z >> 12);
83 *q++ = 0x80 | ((z >> 6) & 0x3f);
84 *q++ = 0x80 | (z & 0x3f);
85 b -= 3;
86 } else {
87 /* 110xxxxx 10xxxxxx */
88 if (b < 2)
89 break;
90 *q++ = 0xc0 | (z >> 6);
91 *q++ = 0x80 | (z & 0x3f);
92 b -= 2;
93 }
94 } else {
95 /* 0xxxxxxx */
96 if (!b)
97 break;
98 *q++ = z;
99 b -= 1;
100 }
101 p += 2;
102 a -= 1;
103 }
104 *inbuf = (const char *)p;
105 *outbuf = (char *)q;
106 *inbytesleft = a << 1;
107 *outbytesleft = b;
108 /* We just did a generic 1:1 conversion that is fully reversible.
109 * Furthermore, code below only tests for (size_t)-1.
110 */
111 return 0;
112 }
113 #endif
114
115
116 typedef struct {
117 const uint8_t *buffer;
118 const uint8_t *p;
119 const uint8_t *end;
120 } asf_reader_t;
121
122 typedef struct {
123 asf_header_t pub;
124
125 /* private part */
126 uint8_t *raw_data;
127 int number_count;
128 uint16_t numbers[ASF_MAX_NUM_STREAMS];
129 uint32_t bitrate_offsets[ASF_MAX_NUM_STREAMS];
130 } asf_header_internal_t;
131
132
asf_reader_init(asf_reader_t * reader,const uint8_t * buffer,int size)133 static void asf_reader_init (asf_reader_t *reader, const uint8_t *buffer, int size) {
134 if (size < 0)
135 size = 0;
136 reader->buffer =
137 reader->p = buffer;
138 reader->end = buffer + size;
139 }
140
asf_reader_get_block(asf_reader_t * reader,uint32_t n)141 static const uint8_t *asf_reader_get_block (asf_reader_t *reader, uint32_t n) {
142 const uint8_t *p;
143 if ((uint32_t)(reader->end - reader->p) < n)
144 return NULL;
145 p = reader->p;
146 reader->p += n;
147 return p;
148 }
149
asf_reader_get_bytes(asf_reader_t * reader,uint32_t size)150 static uint8_t *asf_reader_get_bytes (asf_reader_t *reader, uint32_t size) {
151 uint8_t *buffer;
152 if (!size)
153 return NULL;
154 if ((uint32_t)(reader->end - reader->p) < size)
155 return NULL;
156 buffer = malloc (size);
157 if (!buffer)
158 return NULL;
159 memcpy (buffer, reader->p, size);
160 reader->p += size;
161 return buffer;
162 }
163
164 /* get an utf8 string */
asf_reader_get_string(asf_reader_t * reader,size_t size,iconv_t cd)165 static char *asf_reader_get_string(asf_reader_t *reader, size_t size, iconv_t cd) {
166 char *inbuf, *outbuf;
167 size_t inbytesleft, outbytesleft;
168 char scratch[2048];
169
170 if ((size == 0) || ((uint32_t)(reader->end - reader->p) < size))
171 return NULL;
172
173 inbuf = (char *)reader->p;
174 inbytesleft = size;
175 outbuf = scratch;
176 outbytesleft = sizeof (scratch) - 1;
177 reader->p += size;
178 if (iconv (cd, (ICONV_CONST char **)&inbuf, &inbytesleft, &outbuf, &outbytesleft) != (size_t)-1) {
179 /* Those utf16 input strings normally are 0 terminated, but just in case... */
180 scratch[sizeof (scratch) - 1 - outbytesleft] = 0;
181 return strdup(scratch);
182 } else {
183 lprintf("iconv error\n");
184 return NULL;
185 }
186 }
187
asf_reader_skip(asf_reader_t * reader,uint32_t size)188 static int asf_reader_skip (asf_reader_t *reader, uint32_t size) {
189 if ((uint32_t)(reader->end - reader->p) < size) {
190 reader->p = reader->end;
191 return 0;
192 }
193 reader->p += size;
194 return size;
195 }
196
asf_reader_get_buffer(asf_reader_t * reader)197 static const uint8_t *asf_reader_get_buffer(asf_reader_t *reader) {
198 return reader->p;
199 }
200
asf_reader_eos(asf_reader_t * reader)201 static int asf_reader_eos (asf_reader_t *reader) {
202 return reader->p >= reader->end;
203 }
204
asf_reader_get_size(asf_reader_t * reader)205 static size_t asf_reader_get_size(asf_reader_t *reader) {
206 return reader->end - reader->p;
207 }
208
209 /* Manage id mapping */
asf_header_get_stream_id(asf_header_t * header_pub,uint16_t stream_number)210 static int asf_header_get_stream_id(asf_header_t *header_pub, uint16_t stream_number) {
211 asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
212 int i;
213
214 /* linear search */
215 for (i = 0; i < header->number_count; i++) {
216 if (stream_number == header->numbers[i]) {
217 lprintf("asf_header_get_stream_id: id found: %d\n", i);
218 return i;
219 }
220 }
221
222 /* not found */
223 if (header->number_count >= ASF_MAX_NUM_STREAMS)
224 return -1;
225
226 header->numbers[header->number_count] = stream_number;
227 header->number_count++;
228 return header->number_count - 1;
229 }
230
asf_header_parse_file_properties(asf_header_t * header,const uint8_t * buffer,int buffer_len)231 static int asf_header_parse_file_properties(asf_header_t *header, const uint8_t *buffer, int buffer_len) {
232 asf_reader_t reader;
233 asf_file_t *asf_file;
234 const uint8_t *p;
235 uint32_t flags = 0;
236
237 asf_reader_init (&reader, buffer, buffer_len);
238 p = asf_reader_get_block (&reader, 16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4);
239 if (!p)
240 return 0;
241
242 asf_file = malloc (sizeof (*asf_file));
243 if (!asf_file) {
244 lprintf("cannot allocate asf_file_struct\n");
245 return 0;
246 }
247
248 /* full init here, no need to 0 first. */
249 memcpy (asf_file->file_id, p, 16); p += 16;
250 asf_file->file_size = _X_LE_64 (p); p += 8;
251
252 /* creation date */ p += 8;
253 asf_file->data_packet_count = _X_LE_64 (p); p += 8;
254 asf_file->play_duration = _X_LE_64 (p); p += 8;
255 asf_file->send_duration = _X_LE_64 (p); p += 8;
256 asf_file->preroll = _X_LE_64 (p); p += 8;
257
258 flags = _X_LE_32 (p); p += 4;
259 asf_file->packet_size = _X_LE_32 (p); p += 4;
260
261 /* duplicated packet size */ p += 4;
262 asf_file->max_bitrate = _X_LE_32 (p); p += 4;
263
264 asf_file->broadcast_flag = flags & 0x1;
265 asf_file->seekable_flag = flags & 0x2;
266
267 header->file = asf_file;
268
269 lprintf("File properties\n");
270 lprintf(" file_id: %04X\n", _X_LE_16(&asf_file->file_id[4]));
271 lprintf(" file_size: %"PRIu64"\n", asf_file->file_size);
272 lprintf(" data_packet_count: %"PRIu64"\n", asf_file->data_packet_count);
273 lprintf(" play_duration: %"PRIu64"\n", asf_file->play_duration);
274 lprintf(" send_duration: %"PRIu64"\n", asf_file->send_duration);
275 lprintf(" preroll: %"PRIu64"\n", asf_file->preroll);
276 lprintf(" broadcast_flag: %d\n", asf_file->broadcast_flag);
277 lprintf(" seekable_flag: %d\n", asf_file->seekable_flag);
278 lprintf(" packet_size: %"PRIu32"\n", asf_file->packet_size);
279 lprintf(" max_bitrate: %"PRIu32"\n", asf_file->max_bitrate);
280 return 1;
281 }
282
asf_header_delete_stream_properties(asf_stream_t * asf_stream)283 static void asf_header_delete_stream_properties(asf_stream_t *asf_stream) {
284 if (asf_stream) {
285 free (asf_stream->private_data);
286 free (asf_stream->error_correction_data);
287 free (asf_stream);
288 }
289 }
290
asf_header_parse_stream_properties(asf_header_t * header,const uint8_t * buffer,int buffer_len)291 static int asf_header_parse_stream_properties (asf_header_t *header, const uint8_t *buffer, int buffer_len) {
292 asf_reader_t reader;
293 const uint8_t *p;
294 uint16_t flags = 0;
295 asf_stream_t *asf_stream = NULL;
296 int stream_id;
297
298 asf_reader_init (&reader, buffer, buffer_len);
299 p = asf_reader_get_block (&reader, 16 + 16 + 8 + 4 + 4 + 2 + 4);
300 if (!p)
301 goto exit_error;
302
303 asf_stream = malloc (sizeof (*asf_stream));
304 if (!asf_stream)
305 goto exit_error;
306
307 asf_stream->private_data = NULL;
308 asf_stream->error_correction_data = NULL;
309
310 asf_stream->stream_type = asf_guid_2_num (p); p += 16;
311 asf_stream->error_correction_type = asf_guid_2_num (p); p += 16;
312
313 asf_stream->time_offset = _X_LE_64 (p); p += 8;
314 asf_stream->private_data_length = _X_LE_32 (p); p += 4;
315 asf_stream->error_correction_data_length = _X_LE_32 (p); p += 4;
316
317 flags = _X_LE_16 (p); p += 2;
318 asf_stream->stream_number = flags & 0x7F;
319 asf_stream->encrypted_flag = flags >> 15;
320
321 /* junk */ p += 4;
322
323 if (asf_stream->private_data_length) {
324 asf_stream->private_data = asf_reader_get_bytes (&reader, asf_stream->private_data_length);
325 if (!asf_stream->private_data)
326 goto exit_error;
327 }
328
329 if (asf_stream->error_correction_data_length) {
330 asf_stream->error_correction_data = asf_reader_get_bytes(&reader, asf_stream->error_correction_data_length);
331 if (!asf_stream->error_correction_data)
332 goto exit_error;
333 }
334
335 lprintf("Stream_properties\n");
336 lprintf(" stream_number: %d\n", asf_stream->stream_number);
337 lprintf(" stream_type: %s\n", asf_guid_name (asf_stream->stream_type));
338 lprintf(" error_correction_type: %s\n", asf_guid_name (asf_stream->error_correction_type));
339 lprintf(" time_offset: %"PRIu64"\n", asf_stream->time_offset);
340 lprintf(" private_data_length: %"PRIu32"\n", asf_stream->private_data_length);
341 lprintf(" error_correction_data_length: %"PRIu32"\n", asf_stream->error_correction_data_length);
342 lprintf(" encrypted_flag: %d\n", asf_stream->encrypted_flag);
343
344 stream_id = asf_header_get_stream_id(header, asf_stream->stream_number);
345 if (stream_id >= 0) {
346 header->streams[stream_id] = asf_stream;
347 header->stream_count++;
348 } else {
349 asf_header_delete_stream_properties(asf_stream);
350 }
351 return 1;
352
353 exit_error:
354 asf_header_delete_stream_properties(asf_stream);
355 return 0;
356 }
357
asf_header_delete_stream_extended_properties(asf_stream_extension_t * asf_stream_extension)358 static void asf_header_delete_stream_extended_properties(asf_stream_extension_t *asf_stream_extension) {
359 if (asf_stream_extension) {
360 if (asf_stream_extension->stream_names) {
361 int i;
362 for (i = 0; i < asf_stream_extension->stream_name_count; i++)
363 free (asf_stream_extension->stream_names[i]);
364 free (asf_stream_extension->stream_names);
365 }
366 free (asf_stream_extension);
367 }
368 }
369
asf_header_parse_stream_extended_properties(asf_header_t * header,const uint8_t * buffer,int buffer_len)370 static int asf_header_parse_stream_extended_properties (asf_header_t *header, const uint8_t *buffer, int buffer_len) {
371 asf_reader_t reader;
372 const uint8_t *p;
373 uint32_t flags = 0;
374 uint16_t stream_number = 0;
375 int i;
376 int stream_id;
377 asf_stream_extension_t *asf_stream_extension;
378
379 asf_reader_init (&reader, buffer, buffer_len);
380 p = asf_reader_get_block (&reader, 2 * 8 + 7 * 4 + 4 + 2 + 2 + 8 + 2 + 2);
381 if (!p)
382 return 0;
383
384 asf_stream_extension = malloc (sizeof (*asf_stream_extension));
385 if (!asf_stream_extension)
386 return 0;
387
388 asf_stream_extension->stream_names = NULL;
389
390 asf_stream_extension->start_time = _X_LE_64 (p); p += 8;
391 asf_stream_extension->end_time = _X_LE_64 (p); p += 8;
392
393 asf_stream_extension->data_bitrate = _X_LE_32 (p); p += 4;
394 asf_stream_extension->buffer_size = _X_LE_32 (p); p += 4;
395 asf_stream_extension->initial_buffer_fullness = _X_LE_32 (p); p += 4;
396 asf_stream_extension->alternate_data_bitrate = _X_LE_32 (p); p += 4;
397 asf_stream_extension->alternate_buffer_size = _X_LE_32 (p); p += 4;
398 asf_stream_extension->alternate_initial_buffer_fullness = _X_LE_32 (p); p += 4;
399 asf_stream_extension->max_object_size = _X_LE_32 (p); p += 4;
400
401 /* 4 flags */
402 flags = _X_LE_32 (p); p += 4;
403 asf_stream_extension->reliable_flag = flags & 1;
404 asf_stream_extension->seekable_flag = (flags >> 1) & 1;
405 asf_stream_extension->no_cleanpoints_flag = (flags >> 2) & 1;
406 asf_stream_extension->resend_live_cleanpoints_flag = (flags >> 3) & 1;
407
408 stream_number = _X_LE_16 (p); p += 2;
409 asf_stream_extension->language_id = _X_LE_16 (p); p += 2;
410
411 asf_stream_extension->average_time_per_frame = _X_LE_64 (p); p += 8;
412
413 asf_stream_extension->stream_name_count = _X_LE_16 (p); p += 2;
414 asf_stream_extension->payload_extension_system_count = _X_LE_16 (p); p += 2;
415
416 /* get stream names */
417 if (asf_stream_extension->stream_name_count) {
418 asf_stream_extension->stream_names = malloc (asf_stream_extension->stream_name_count * sizeof (void*));
419 for (i = 0; i < asf_stream_extension->stream_name_count; i++) {
420 char *name;
421 uint16_t length;
422 p = asf_reader_get_block (&reader, 2 + 2); /* lang_index, length */
423 if (!p)
424 break;
425 length = _X_LE_16 (p + 2);
426 name = (char*)asf_reader_get_bytes (&reader, length); /* store them */
427 if (asf_stream_extension->stream_names)
428 asf_stream_extension->stream_names[i] = name;
429 else
430 free(name);
431 }
432 }
433
434 /* skip payload extensions */
435 for (i = 0; i < asf_stream_extension->payload_extension_system_count; i++) {
436 uint32_t length;
437 p = asf_reader_get_block (&reader, 16 + 2 + 4); /* guid, data_size, length */
438 if (!p)
439 break;
440 length = _X_LE_32 (p + 16 + 2);
441 asf_reader_skip (&reader, length);
442 }
443
444 stream_id = asf_header_get_stream_id(header, stream_number);
445 if (stream_id >= 0) {
446 header->stream_extensions[stream_id] = asf_stream_extension;
447 }
448
449 /* embeded stream properties */
450 p = asf_reader_get_block (&reader, 16 + 8);
451 if (p) {
452 uint64_t object_length = _X_LE_64 (p + 16);
453 /* check length validity */
454 if (asf_reader_get_size(&reader) == (object_length - 24)) {
455 asf_guid_t object_id = asf_guid_2_num (p);
456 switch (object_id) {
457 case GUID_ASF_STREAM_PROPERTIES:
458 asf_header_parse_stream_properties(header, asf_reader_get_buffer(&reader), object_length - 24);
459 break;
460 default:
461 lprintf ("unexpected object\n");
462 break;
463 }
464 } else {
465 lprintf ("invalid object length\n");
466 }
467 }
468
469 lprintf("Stream extension properties\n");
470 lprintf(" stream_number: %"PRIu16"\n", stream_number);
471 lprintf(" start_time: %"PRIu64"\n", asf_stream_extension->start_time);
472 lprintf(" end_time: %"PRIu64"\n", asf_stream_extension->end_time);
473 lprintf(" data_bitrate: %"PRIu32"\n", asf_stream_extension->data_bitrate);
474 lprintf(" buffer_size: %"PRIu32"\n", asf_stream_extension->buffer_size);
475 lprintf(" initial_buffer_fullness: %"PRIu32"\n", asf_stream_extension->initial_buffer_fullness);
476 lprintf(" alternate_data_bitrate: %"PRIu32"\n", asf_stream_extension->alternate_data_bitrate);
477 lprintf(" alternate_buffer_size: %"PRIu32"\n", asf_stream_extension->alternate_buffer_size);
478 lprintf(" alternate_initial_buffer_fullness: %"PRIu32"\n", asf_stream_extension->alternate_initial_buffer_fullness);
479 lprintf(" max_object_size: %"PRIu32"\n", asf_stream_extension->max_object_size);
480 lprintf(" language_id: %"PRIu16"\n", asf_stream_extension->language_id);
481 lprintf(" average_time_per_frame: %"PRIu64"\n", asf_stream_extension->average_time_per_frame);
482 lprintf(" stream_name_count: %"PRIu16"\n", asf_stream_extension->stream_name_count);
483 lprintf(" payload_extension_system_count: %"PRIu16"\n", asf_stream_extension->payload_extension_system_count);
484 lprintf(" reliable_flag: %d\n", asf_stream_extension->reliable_flag);
485 lprintf(" seekable_flag: %d\n", asf_stream_extension->seekable_flag);
486 lprintf(" no_cleanpoints_flag: %d\n", asf_stream_extension->no_cleanpoints_flag);
487 lprintf(" resend_live_cleanpoints_flag: %d\n", asf_stream_extension->resend_live_cleanpoints_flag);
488
489 if (stream_id < 0) {
490 asf_header_delete_stream_extended_properties(asf_stream_extension);
491 }
492
493 return 1;
494 }
495
asf_header_parse_stream_bitrate_properties(asf_header_t * header_pub,const uint8_t * buffer,int buffer_len)496 static int asf_header_parse_stream_bitrate_properties (asf_header_t *header_pub, const uint8_t *buffer, int buffer_len) {
497 asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
498 asf_reader_t reader;
499 const uint8_t *p;
500 uint16_t bitrate_count = 0;
501 int i;
502 int stream_id;
503
504 asf_reader_init (&reader, buffer, buffer_len);
505 p = asf_reader_get_block (&reader, 2);
506 if (!p)
507 return 0;
508 bitrate_count = _X_LE_16 (p);
509 p = asf_reader_get_block (&reader, 6 * bitrate_count);
510 if (!p)
511 return 0;
512
513 lprintf (" bitrate count: %d\n", bitrate_count);
514
515 for(i = 0; i < bitrate_count; i++) {
516 uint16_t flags = 0;
517 uint32_t bitrate = 0;
518 int stream_number;
519 uint32_t bitrate_offs;
520
521 flags = _X_LE_16 (p); p += 2;
522 stream_number = flags & 0x7f;
523
524 bitrate_offs = p - (const uint8_t *)(header->raw_data);
525 bitrate = _X_LE_32 (p); p += 4;
526 lprintf (" stream num %d, bitrate %"PRIu32"\n", stream_number, bitrate);
527
528 stream_id = asf_header_get_stream_id(&header->pub, stream_number);
529 if (stream_id >= 0) {
530 header->pub.bitrates[stream_id] = bitrate;
531 header->bitrate_offsets[stream_id] = bitrate_offs;
532 }
533 }
534 return 1;
535 }
536
asf_header_parse_metadata(asf_header_t * header_pub,const uint8_t * buffer,int buffer_len)537 static int asf_header_parse_metadata (asf_header_t *header_pub, const uint8_t *buffer, int buffer_len)
538 {
539 asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
540 asf_reader_t reader;
541 const uint8_t *p;
542 uint16_t i, records_count = 0;
543
544 if (buffer_len < 2)
545 return 0;
546
547 asf_reader_init (&reader, buffer, buffer_len);
548 p = asf_reader_get_block (&reader, 2);
549 if (!p)
550 return 0;
551
552 records_count = _X_LE_16 (p);
553
554 for (i = 0; i < records_count; i++)
555 {
556 uint16_t index, stream = 0, name_len = 0, data_type;
557 uint32_t data_len = 0;
558 int stream_id;
559
560 p = asf_reader_get_block (&reader, 4 * 2 + 4);
561 if (!p)
562 break;
563
564 index = _X_LE_16 (p); p += 2;
565 stream = _X_LE_16 (p); p += 2;
566 stream &= 0x7f;
567 name_len = _X_LE_16 (p); p += 2;
568 data_type = _X_LE_16 (p); p += 2;
569 data_len = _X_LE_32 (p); p += 4;
570
571 /* not used yet */
572 (void)index;
573 (void)data_type;
574
575 stream_id = asf_header_get_stream_id (&header->pub, stream);
576
577 if (stream_id >= 0 && data_len >= 4) {
578 static const uint8_t name_ar[] = {'A',0,'s',0,'p',0,'e',0,'c',0,'t',0,'R',0,'a',0,'t',0,'i',0,'o',0};
579 static const uint8_t name_x[] = {'X',0,0,0};
580 static const uint8_t name_y[] = {'Y',0,0,0};
581 const uint8_t *p = asf_reader_get_block (&reader, name_len);
582 if (p && (name_len >= sizeof (name_ar) + sizeof (name_x)) && !memcmp (p, name_ar, sizeof (name_ar))) {
583 if (!memcmp (p + sizeof (name_ar), name_x, sizeof (name_x))) {
584 p = asf_reader_get_block (&reader, 4);
585 if (!p)
586 break;
587 header->pub.aspect_ratios[stream_id].x = _X_LE_32 (p);
588 data_len -= 4;
589 }
590 else if (!memcmp (p + sizeof (name_ar), name_y, sizeof (name_y))) {
591 p = asf_reader_get_block (&reader, 4);
592 if (!p)
593 break;
594 header->pub.aspect_ratios[stream_id].y = _X_LE_32 (p);
595 data_len -= 4;
596 }
597 }
598 asf_reader_skip (&reader, data_len);
599 } else {
600 /* avoid uint32_t overflow */
601 asf_reader_skip (&reader, name_len);
602 asf_reader_skip (&reader, data_len);
603 }
604 }
605
606 return 1;
607 }
608
asf_header_parse_header_extension(asf_header_t * header,const uint8_t * buffer,int buffer_len)609 static int asf_header_parse_header_extension (asf_header_t *header, const uint8_t *buffer, int buffer_len) {
610 asf_reader_t reader;
611 const uint8_t *p;
612 uint32_t data_length;
613
614 asf_reader_init (&reader, buffer, buffer_len);
615 p = asf_reader_get_block (&reader, 16 + 2 + 4); /* guid, junk, data_length */
616 if (!p)
617 return 0;
618 data_length = _X_LE_32 (p + 16 + 2);
619 lprintf("parse_asf_header_extension: length: %"PRIu32"\n", data_length);
620 /* used in LOG mode only */
621 (void)data_length;
622
623 while (!asf_reader_eos(&reader)) {
624
625 asf_guid_t object_id;
626 uint64_t object_length;
627 uint32_t object_data_length;
628
629 p = asf_reader_get_block (&reader, 16 + 8);
630 if (!p) {
631 printf("invalid buffer size\n");
632 return 0;
633 }
634
635 object_length = _X_LE_64 (p + 16);
636 if (object_length & ~(uint64_t)0xffffffff)
637 return 0;
638 if ((uint32_t)object_length < 24)
639 return 0;
640 object_data_length = object_length - 24;
641 object_id = asf_guid_2_num (p);
642
643 switch (object_id) {
644 case GUID_EXTENDED_STREAM_PROPERTIES:
645 asf_header_parse_stream_extended_properties(header, asf_reader_get_buffer(&reader), object_data_length);
646 break;
647 case GUID_METADATA:
648 asf_header_parse_metadata(header, asf_reader_get_buffer(&reader), object_data_length);
649 break;
650 case GUID_ADVANCED_MUTUAL_EXCLUSION:
651 case GUID_GROUP_MUTUAL_EXCLUSION:
652 case GUID_STREAM_PRIORITIZATION:
653 case GUID_BANDWIDTH_SHARING:
654 case GUID_LANGUAGE_LIST:
655 case GUID_METADATA_LIBRARY:
656 case GUID_INDEX_PARAMETERS:
657 case GUID_MEDIA_OBJECT_INDEX_PARAMETERS:
658 case GUID_TIMECODE_INDEX_PARAMETERS:
659 case GUID_ADVANCED_CONTENT_ENCRYPTION:
660 case GUID_COMPATIBILITY:
661 case GUID_ASF_PADDING:
662 break;
663 default:
664 lprintf ("unexpected object\n");
665 break;
666 }
667 asf_reader_skip(&reader, object_data_length);
668 }
669 return 1;
670 }
671
asf_header_parse_content_description(asf_header_t * header_pub,const uint8_t * buffer,int buffer_len)672 static int asf_header_parse_content_description (asf_header_t *header_pub, const uint8_t *buffer, int buffer_len) {
673 asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
674 asf_reader_t reader;
675 const uint8_t *p;
676 asf_content_t *content;
677 uint16_t title_length = 0, author_length = 0, copyright_length = 0, description_length = 0, rating_length = 0;
678 iconv_t iconv_cd;
679
680 asf_reader_init (&reader, buffer, buffer_len);
681 p = asf_reader_get_block (&reader, 5 * 2);
682 if (!p)
683 return 0;
684
685 content = malloc (sizeof (*content));
686 if (!content)
687 return 0;
688
689 if ( (iconv_cd = iconv_open("UTF-8", "UCS-2LE")) == (iconv_t)-1 ) {
690 free(content);
691 return 0;
692 }
693
694 /* full init here, no need to 0 first. */
695 title_length = _X_LE_16 (p);
696 author_length = _X_LE_16 (p + 2);
697 copyright_length = _X_LE_16 (p + 4);
698 description_length = _X_LE_16 (p + 6);
699 rating_length = _X_LE_16 (p + 8);
700
701 content->title = asf_reader_get_string(&reader, title_length, iconv_cd);
702 content->author = asf_reader_get_string(&reader, author_length, iconv_cd);
703 content->copyright = asf_reader_get_string(&reader, copyright_length, iconv_cd);
704 content->description = asf_reader_get_string(&reader, description_length, iconv_cd);
705 content->rating = asf_reader_get_string(&reader, rating_length, iconv_cd);
706
707 lprintf("title: %d chars: \"%s\"\n", title_length, content->title);
708 lprintf("author: %d chars: \"%s\"\n", author_length, content->author);
709 lprintf("copyright: %d chars: \"%s\"\n", copyright_length, content->copyright);
710 lprintf("description: %d chars: \"%s\"\n", description_length, content->description);
711 lprintf("rating: %d chars: \"%s\"\n", rating_length, content->rating);
712
713 header->pub.content = content;
714
715 iconv_close(iconv_cd);
716 return 1;
717 }
718
719
asf_header_new(uint8_t * buffer,int buffer_len)720 asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) {
721
722 asf_header_internal_t *asf_header;
723 asf_reader_t reader;
724 const uint8_t *p;
725 uint32_t object_count;
726 #ifndef HAVE_ZERO_SAFE_MEM
727 int i;
728 #endif
729 lprintf("parsing_asf_header\n");
730 if (buffer_len < 6) {
731 printf("invalid buffer size\n");
732 return NULL;
733 }
734
735 asf_header = calloc (1, sizeof (*asf_header));
736 if (!asf_header)
737 return NULL;
738 #ifndef HAVE_ZERO_SAFE_MEM
739 asf_header->pub.file = NULL;
740 asf_header->pub.content = NULL;
741 asf_header->pub.stream_count = 0;
742 asf_header->number_count = 0;
743 for (i = 0; i < ASF_MAX_NUM_STREAMS; i++) {
744 asf_header->pub.streams[i] = NULL;
745 asf_header->pub.stream_extensions[i] = NULL;
746 asf_header->pub.bitrates[i] = 0;
747 asf_header->pub.aspect_ratios[i].x = 0;
748 asf_header->pub.aspect_ratios[i].y = 0;
749 asf_header->numbers[i] = 0;
750 asf_header->bitrate_offsets[i] = 0;
751 }
752 #endif
753 asf_header->raw_data = buffer;
754
755 asf_reader_init (&reader, buffer, buffer_len);
756 p = asf_reader_get_block (&reader, 4 + 2);
757 if (!p)
758 goto exit_error;
759
760 object_count = _X_LE_32 (p);
761 /* not used yet */
762 (void)object_count;
763
764 while (!asf_reader_eos(&reader)) {
765
766 asf_guid_t object_id;
767 uint64_t object_length;
768 uint32_t object_data_length;
769
770 p = asf_reader_get_block (&reader, 16 + 8);
771 if (!p) {
772 printf("invalid buffer size\n");
773 goto exit_error;
774 }
775
776 object_length = _X_LE_64 (p + 16);
777 if (object_length & ~(uint64_t)0xffffffff)
778 goto exit_error;
779 if ((uint32_t)object_length < 24)
780 goto exit_error;
781 object_data_length = object_length - 24;
782 object_id = asf_guid_2_num (p);
783
784 switch (object_id) {
785
786 case GUID_ASF_FILE_PROPERTIES:
787 asf_header_parse_file_properties(&asf_header->pub, asf_reader_get_buffer(&reader), object_data_length);
788 break;
789
790 case GUID_ASF_STREAM_PROPERTIES:
791 asf_header_parse_stream_properties(&asf_header->pub, asf_reader_get_buffer(&reader), object_data_length);
792 break;
793
794 case GUID_ASF_STREAM_BITRATE_PROPERTIES:
795 asf_header_parse_stream_bitrate_properties(&asf_header->pub, asf_reader_get_buffer(&reader), object_data_length);
796 break;
797
798 case GUID_ASF_HEADER_EXTENSION:
799 asf_header_parse_header_extension(&asf_header->pub, asf_reader_get_buffer(&reader), object_data_length);
800 break;
801
802 case GUID_ASF_CONTENT_DESCRIPTION:
803 asf_header_parse_content_description(&asf_header->pub, asf_reader_get_buffer(&reader), object_data_length);
804 break;
805
806 case GUID_ASF_CODEC_LIST:
807 case GUID_ASF_SCRIPT_COMMAND:
808 case GUID_ASF_MARKER:
809 case GUID_ASF_BITRATE_MUTUAL_EXCLUSION:
810 case GUID_ASF_ERROR_CORRECTION:
811 case GUID_ASF_EXTENDED_CONTENT_DESCRIPTION:
812 case GUID_ASF_EXTENDED_CONTENT_ENCRYPTION:
813 case GUID_ASF_PADDING:
814 break;
815
816 default:
817 lprintf ("unexpected object\n");
818 break;
819 }
820 asf_reader_skip(&reader, object_data_length);
821 }
822
823 /* basic checks */
824 if (!asf_header->pub.file) {
825 lprintf("no file object present\n");
826 goto exit_error;
827 }
828 if (!asf_header->pub.content) {
829 lprintf("no content object present\n");
830 asf_header->pub.content = calloc(1, sizeof(asf_content_t));
831 if (!asf_header->pub.content)
832 goto exit_error;
833 }
834
835 return &asf_header->pub;
836
837 exit_error:
838 asf_header_delete(&asf_header->pub);
839 return NULL;
840 }
841
842
asf_header_delete_file_properties(asf_file_t * asf_file)843 static void asf_header_delete_file_properties(asf_file_t *asf_file) {
844 free(asf_file);
845 }
846
asf_header_delete_content(asf_content_t * asf_content)847 static void asf_header_delete_content(asf_content_t *asf_content) {
848 if (asf_content) {
849 free (asf_content->title);
850 free (asf_content->author);
851 free (asf_content->copyright);
852 free (asf_content->description);
853 free (asf_content->rating);
854 free (asf_content);
855 }
856 }
857
asf_header_delete(asf_header_t * header_pub)858 void asf_header_delete (asf_header_t *header_pub) {
859 asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
860 if (header) {
861 int i;
862 asf_header_delete_file_properties (header->pub.file);
863 asf_header_delete_content (header->pub.content);
864 for (i = 0; i < ASF_MAX_NUM_STREAMS; i++) {
865 asf_header_delete_stream_properties (header->pub.streams[i]);
866 asf_header_delete_stream_extended_properties (header->pub.stream_extensions[i]);
867 }
868 free (header);
869 }
870 }
871
872 /* Given a bandwidth, select the best stream */
asf_header_choose_stream(asf_header_internal_t * header,int stream_type,uint32_t bandwidth)873 static int asf_header_choose_stream (asf_header_internal_t *header, int stream_type,
874 uint32_t bandwidth) {
875 int i;
876 int max_lt, min_gt;
877
878 max_lt = min_gt = -1;
879 for (i = 0; i < header->pub.stream_count; i++) {
880 if ((int)header->pub.streams[i]->stream_type == stream_type) {
881 if (header->pub.bitrates[i] <= bandwidth) {
882 if ((max_lt == -1) || (header->pub.bitrates[i] > header->pub.bitrates[max_lt]))
883 max_lt = i;
884 } else {
885 if ((min_gt == -1) || (header->pub.bitrates[i] < header->pub.bitrates[min_gt]))
886 min_gt = i;
887 }
888 }
889 }
890
891 return (max_lt != -1) ? max_lt : min_gt;
892 }
893
asf_header_choose_streams(asf_header_t * header_pub,uint32_t bandwidth,int * video_id,int * audio_id)894 void asf_header_choose_streams (asf_header_t *header_pub, uint32_t bandwidth,
895 int *video_id, int *audio_id) {
896 asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
897 uint32_t bandwidth_left;
898
899 *video_id = *audio_id = -1;
900 bandwidth_left = bandwidth;
901
902 lprintf("%d streams, bandwidth %"PRIu32"\n", header->pub.stream_count, bandwidth_left);
903
904 /* choose a video stream adapted to the user bandwidth */
905 *video_id = asf_header_choose_stream (header, GUID_ASF_VIDEO_MEDIA, bandwidth_left);
906 if (*video_id != -1) {
907 if (header->pub.bitrates[*video_id] < bandwidth_left) {
908 bandwidth_left -= header->pub.bitrates[*video_id];
909 } else {
910 bandwidth_left = 0;
911 }
912 lprintf("selected video stream %d, bandwidth left: %"PRIu32"\n",
913 header->pub.streams[*video_id]->stream_number, bandwidth_left);
914 } else {
915 lprintf("no video stream\n");
916 }
917
918 /* choose a audio stream adapted to the user bandwidth */
919 *audio_id = asf_header_choose_stream (header, GUID_ASF_AUDIO_MEDIA, bandwidth_left);
920 if (*audio_id != -1) {
921 if (header->pub.bitrates[*audio_id] < bandwidth_left) {
922 bandwidth_left -= header->pub.bitrates[*audio_id];
923 } else {
924 bandwidth_left = 0;
925 }
926 lprintf("selected audio stream %d, bandwidth left: %"PRIu32"\n",
927 header->pub.streams[*audio_id]->stream_number, bandwidth_left);
928 } else {
929 lprintf("no audio stream\n");
930 }
931 }
932
asf_header_disable_streams(asf_header_t * header_pub,int video_id,int audio_id)933 void asf_header_disable_streams (asf_header_t *header_pub, int video_id, int audio_id) {
934 asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
935 int i;
936
937 for (i = 0; i < header->pub.stream_count; i++) {
938 asf_guid_t stream_type = header->pub.streams[i]->stream_type;
939
940 if (header->bitrate_offsets[i] &&
941 (((stream_type == GUID_ASF_VIDEO_MEDIA) && (i != video_id)) ||
942 ((stream_type == GUID_ASF_AUDIO_MEDIA) && (i != audio_id)))) {
943 /* XXX: Only used by input/mmsh.c. Tweak the raw header data for later reinterpretation
944 * by demuxer. Do NOT call this after freeing raw buffer!!
945 */
946 uint8_t *bitrate_pointer = header->raw_data + header->bitrate_offsets[i];
947 /* disable the stream */
948 lprintf("stream %d disabled\n", header->pub.streams[i]->stream_number);
949 *bitrate_pointer++ = 0;
950 *bitrate_pointer++ = 0;
951 *bitrate_pointer++ = 0;
952 *bitrate_pointer = 0;
953 }
954 }
955 }
956
957 static const asf_guid_t sorted_nums[] = {
958 GUID_ERROR,
959 GUID_ASF_NO_ERROR_CORRECTION,
960 GUID_ASF_JFIF_MEDIA,
961 GUID_ASF_MUTEX_BITRATE,
962 GUID_ASF_MARKER,
963 GUID_ASF_MUTEX_UKNOWN,
964 GUID_ASF_RESERVED_1,
965 GUID_ASF_EXTENDED_CONTENT_ENCRYPTION,
966 GUID_ASF_RESERVED_MARKER,
967 GUID_ASF_FILE_TRANSFER_MEDIA,
968 GUID_ASF_SCRIPT_COMMAND,
969 GUID_ASF_HEADER,
970 GUID_ASF_CONTENT_DESCRIPTION,
971 GUID_ADVANCED_CONTENT_ENCRYPTION,
972 GUID_ASF_ERROR_CORRECTION,
973 GUID_ASF_DATA,
974 GUID_ASF_CODEC_LIST,
975 GUID_GROUP_MUTUAL_EXCLUSION,
976 GUID_ASF_AUDIO_MEDIA,
977 GUID_ASF_EXTENDED_CONTENT_DESCRIPTION,
978 GUID_ASF_AUDIO_CONCEAL_NONE,
979 GUID_ASF_CODEC_COMMENT1_HEADER,
980 GUID_ASF_AUDIO_SPREAD,
981 GUID_STREAM_PRIORITIZATION,
982 GUID_COMPATIBILITY,
983 GUID_TIMECODE_INDEX_PARAMETERS,
984 GUID_ASF_PADDING,
985 GUID_ASF_SIMPLE_INDEX,
986 GUID_ASF_STREAM_PROPERTIES,
987 GUID_METADATA_LIBRARY,
988 GUID_ASF_FILE_PROPERTIES,
989 GUID_LANGUAGE_LIST,
990 GUID_MEDIA_OBJECT_INDEX_PARAMETERS,
991 GUID_ASF_HEADER_EXTENSION,
992 GUID_ASF_COMMAND_MEDIA,
993 GUID_ASF_VIDEO_MEDIA,
994 GUID_EXTENDED_STREAM_PROPERTIES,
995 GUID_ASF_STREAM_BITRATE_PROPERTIES,
996 GUID_ADVANCED_MUTUAL_EXCLUSION,
997 GUID_TIMECODE_INDEX,
998 GUID_ASF_2_0_HEADER,
999 GUID_INDEX,
1000 GUID_ASF_BITRATE_MUTUAL_EXCLUSION,
1001 GUID_INDEX_PARAMETERS,
1002 GUID_ASF_DEGRADABLE_JPEG_MEDIA,
1003 GUID_ASF_BINARY_MEDIA,
1004 GUID_ASF_RESERVED_SCRIPT_COMMNAND,
1005 GUID_BANDWIDTH_SHARING,
1006 GUID_METADATA,
1007 GUID_MEDIA_OBJECT_INDEX
1008 };
1009
1010 static const uint8_t sorted_guids[] = {
1011 0x00,0x00,0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* GUID_ERROR */
1012 0x00,0x57,0xfb,0x20, 0x55,0x5b, 0xcf,0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b, /* GUID_ASF_NO_ERROR_CORRECTION */
1013 0x00,0xe1,0x1b,0xb6, 0x4e,0x5b, 0xcf,0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b, /* GUID_ASF_JFIF_MEDIA */
1014 0x01,0x2a,0xe2,0xd6, 0xda,0x35, 0xd1,0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe, /* GUID_ASF_MUTEX_BITRATE */
1015 0x01,0xcd,0x87,0xf4, 0x51,0xa9, 0xcf,0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65, /* GUID_ASF_MARKER */
1016 0x02,0x2a,0xe2,0xd6, 0xda,0x35, 0xd1,0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe, /* GUID_ASF_MUTEX_UKNOWN */
1017 0x11,0xd2,0xd3,0xab, 0xba,0xa9, 0xcf,0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65, /* GUID_ASF_RESERVED_1 */
1018 0x14,0xe6,0x8a,0x29, 0x22,0x26, 0x17,0x4c, 0xb9, 0x35, 0xda, 0xe0, 0x7e, 0xe9, 0x28, 0x9c, /* GUID_ASF_EXTENDED_CONTENT_ENCRYPTION */
1019 0x20,0xdb,0xfe,0x4c, 0xf6,0x75, 0xcf,0x11, 0x9c, 0x0f, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb, /* GUID_ASF_RESERVED_MARKER */
1020 0x2c,0x22,0xbd,0x91, 0x1c,0xf2, 0x7a,0x49, 0x8b, 0x6d, 0x5a, 0xa8, 0x6b, 0xfc, 0x01, 0x85, /* GUID_ASF_FILE_TRANSFER_MEDIA */
1021 0x30,0x1a,0xfb,0x1e, 0x62,0x0b, 0xd0,0x11, 0xa3, 0x9b, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6, /* GUID_ASF_SCRIPT_COMMAND */
1022 0x30,0x26,0xb2,0x75, 0x8e,0x66, 0xcf,0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c, /* GUID_ASF_HEADER */
1023 0x33,0x26,0xb2,0x75, 0x8e,0x66, 0xcf,0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c, /* GUID_ASF_CONTENT_DESCRIPTION */
1024 0x33,0x85,0x05,0x43, 0x81,0x69, 0xe6,0x49, 0x9b, 0x74, 0xad, 0x12, 0xcb, 0x86, 0xd5, 0x8c, /* GUID_ADVANCED_CONTENT_ENCRYPTION */
1025 0x35,0x26,0xb2,0x75, 0x8e,0x66, 0xcf,0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c, /* GUID_ASF_ERROR_CORRECTION */
1026 0x36,0x26,0xb2,0x75, 0x8e,0x66, 0xcf,0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c, /* GUID_ASF_DATA */
1027 0x40,0x52,0xd1,0x86, 0x1d,0x31, 0xd0,0x11, 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6, /* GUID_ASF_CODEC_LIST */
1028 0x40,0x5a,0x46,0xd1, 0x79,0x5a, 0x38,0x43, 0xb7, 0x1b, 0xe3, 0x6b, 0x8f, 0xd6, 0xc2, 0x49, /* GUID_GROUP_MUTUAL_EXCLUSION */
1029 0x40,0x9e,0x69,0xf8, 0x4d,0x5b, 0xcf,0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b, /* GUID_ASF_AUDIO_MEDIA */
1030 0x40,0xa4,0xd0,0xd2, 0x07,0xe3, 0xd2,0x11, 0x97, 0xf0, 0x00, 0xa0, 0xc9, 0x5e, 0xa8, 0x50, /* GUID_ASF_EXTENDED_CONTENT_DESCRIPTION */
1031 0x40,0xa4,0xf1,0x49, 0xce,0x4e, 0xd0,0x11, 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6, /* GUID_ASF_AUDIO_CONCEAL_NONE */
1032 0x41,0x52,0xd1,0x86, 0x1d,0x31, 0xd0,0x11, 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6, /* GUID_ASF_CODEC_COMMENT1_HEADER */
1033 0x50,0xcd,0xc3,0xbf, 0x8f,0x61, 0xcf,0x11, 0x8b, 0xb2, 0x00, 0xaa, 0x00, 0xb4, 0xe2, 0x20, /* GUID_ASF_AUDIO_SPREAD */
1034 0x5b,0xd1,0xfe,0xd4, 0xd3,0x88, 0x4f,0x45, 0x81, 0xf0, 0xed, 0x5c, 0x45, 0x99, 0x9e, 0x24, /* GUID_STREAM_PRIORITIZATION */
1035 0x5d,0x8b,0xf1,0x26, 0x84,0x45, 0xec,0x47, 0x9f, 0x5f, 0x0e, 0x65, 0x1f, 0x04, 0x52, 0xc9, /* GUID_COMPATIBILITY */
1036 0x6d,0x49,0x5e,0xf5, 0x97,0x97, 0x5d,0x4b, 0x8c, 0x8b, 0x60, 0x4d, 0xf9, 0x9b, 0xfb, 0x24, /* GUID_TIMECODE_INDEX_PARAMETERS */
1037 0x74,0xd4,0x06,0x18, 0xdf,0xca, 0x09,0x45, 0xa4, 0xba, 0x9a, 0xab, 0xcb, 0x96, 0xaa, 0xe8, /* GUID_ASF_PADDING */
1038 0x90,0x08,0x00,0x33, 0xb1,0xe5, 0xcf,0x11, 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb, /* GUID_ASF_SIMPLE_INDEX */
1039 0x91,0x07,0xdc,0xb7, 0xb7,0xa9, 0xcf,0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65, /* GUID_ASF_STREAM_PROPERTIES */
1040 0x94,0x1c,0x23,0x44, 0x98,0x94, 0xd1,0x49, 0xa1, 0x41, 0x1d, 0x13, 0x4e, 0x45, 0x70, 0x54, /* GUID_METADATA_LIBRARY */
1041 0xa1,0xdc,0xab,0x8c, 0x47,0xa9, 0xcf,0x11, 0x8e, 0xe4, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65, /* GUID_ASF_FILE_PROPERTIES */
1042 0xa9,0x46,0x43,0x7c, 0xe0,0xef, 0xfc,0x4b, 0xb2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85, /* GUID_LANGUAGE_LIST */
1043 0xad,0x3b,0x20,0x6b, 0x11,0x3f, 0xe4,0x48, 0xac, 0xa8, 0xd7, 0x61, 0x3d, 0xe2, 0xcf, 0xa7, /* GUID_MEDIA_OBJECT_INDEX_PARAMETERS */
1044 0xb5,0x03,0xbf,0x5f, 0x2e,0xa9, 0xcf,0x11, 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65, /* GUID_ASF_HEADER_EXTENSION */
1045 0xc0,0xcf,0xda,0x59, 0xe6,0x59, 0xd0,0x11, 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6, /* GUID_ASF_COMMAND_MEDIA */
1046 0xc0,0xef,0x19,0xbc, 0x4d,0x5b, 0xcf,0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b, /* GUID_ASF_VIDEO_MEDIA */
1047 0xcb,0xa5,0xe6,0x14, 0x72,0xc6, 0x32,0x43, 0x83, 0x99, 0xa9, 0x69, 0x52, 0x06, 0x5b, 0x5a, /* GUID_EXTENDED_STREAM_PROPERTIES */
1048 0xce,0x75,0xf8,0x7b, 0x8d,0x46, 0xd1,0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2, /* GUID_ASF_STREAM_BITRATE_PROPERTIES */
1049 0xcf,0x49,0x86,0xa0, 0x75,0x47, 0x70,0x46, 0x8a, 0x16, 0x6e, 0x35, 0x35, 0x75, 0x66, 0xcd, /* GUID_ADVANCED_MUTUAL_EXCLUSION */
1050 0xd0,0x3f,0xb7,0x3c, 0x4a,0x0c, 0x03,0x48, 0x95, 0x3d, 0xed, 0xf7, 0xb6, 0x22, 0x8f, 0x0c, /* GUID_TIMECODE_INDEX */
1051 0xd1,0x29,0xe2,0xd6, 0xda,0x35, 0xd1,0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe, /* GUID_ASF_2_0_HEADER */
1052 0xd3,0x29,0xe2,0xd6, 0xda,0x35, 0xd1,0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe, /* GUID_INDEX */
1053 0xdc,0x29,0xe2,0xd6, 0xda,0x35, 0xd1,0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe, /* GUID_ASF_BITRATE_MUTUAL_EXCLUSION */
1054 0xdf,0x29,0xe2,0xd6, 0xda,0x35, 0xd1,0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe, /* GUID_INDEX_PARAMETERS */
1055 0xe0,0x7d,0x90,0x35, 0x15,0xe4, 0xcf,0x11, 0xa9, 0x17, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b, /* GUID_ASF_DEGRADABLE_JPEG_MEDIA */
1056 0xe2,0x65,0xfb,0x3a, 0xef,0x47, 0xf2,0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43, /* GUID_ASF_BINARY_MEDIA */
1057 0xe3,0xcb,0x1a,0x4b, 0x0b,0x10, 0xd0,0x11, 0xa3, 0x9b, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6, /* GUID_ASF_RESERVED_SCRIPT_COMMNAND */
1058 0xe6,0x09,0x96,0xa6, 0x7b,0x51, 0xd2,0x11, 0xb6, 0xaf, 0x00, 0xc0, 0x4f, 0xd9, 0x08, 0xe9, /* GUID_BANDWIDTH_SHARING */
1059 0xea,0xcb,0xf8,0xc5, 0xaf,0x5b, 0x77,0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca, /* GUID_METADATA */
1060 0xf8,0x03,0xb1,0xfe, 0xad,0x12, 0x64,0x4c, 0x84, 0x0f, 0x2a, 0x1d, 0x2f, 0x7a, 0xd4, 0x8c, /* GUID_MEDIA_OBJECT_INDEX */
1061 };
1062
asf_guid_2_num(const uint8_t * guid)1063 asf_guid_t asf_guid_2_num (const uint8_t *guid) {
1064 int b = 0, m = -1, l, e = sizeof (sorted_guids) >> 4;
1065 do {
1066 const uint8_t *p, *q;
1067 int i;
1068 l = m;
1069 m = (b + e) >> 1;
1070 p = sorted_guids + (m << 4);
1071 q = guid;
1072 i = 16;
1073 do {
1074 int d = (int)*q++ - (int)*p++;
1075 if (d < 0) {
1076 e = m;
1077 break;
1078 } else if (d > 0) {
1079 b = m;
1080 break;
1081 }
1082 i--;
1083 } while (i);
1084 if (!i)
1085 return sorted_nums[m];
1086 } while (m != l);
1087 return sorted_nums[0];
1088 }
1089
1090 static const char tab_hex[16] = "0123456789abcdef";
1091
asf_guid_2_str(uint8_t * str,const uint8_t * guid)1092 void asf_guid_2_str (uint8_t *str, const uint8_t *guid) {
1093 *str++ = tab_hex[guid[3] >> 4];
1094 *str++ = tab_hex[guid[3] & 15];
1095 *str++ = tab_hex[guid[2] >> 4];
1096 *str++ = tab_hex[guid[2] & 15];
1097 *str++ = tab_hex[guid[1] >> 4];
1098 *str++ = tab_hex[guid[1] & 15];
1099 *str++ = tab_hex[guid[0] >> 4];
1100 *str++ = tab_hex[guid[0] & 15];
1101 *str++ = '-';
1102 *str++ = tab_hex[guid[5] >> 4];
1103 *str++ = tab_hex[guid[5] & 15];
1104 *str++ = tab_hex[guid[4] >> 4];
1105 *str++ = tab_hex[guid[4] & 15];
1106 *str++ = '-';
1107 *str++ = tab_hex[guid[7] >> 4];
1108 *str++ = tab_hex[guid[7] & 15];
1109 *str++ = tab_hex[guid[6] >> 4];
1110 *str++ = tab_hex[guid[6] & 15];
1111 *str++ = '-';
1112 guid += 8;
1113 int i = 8;
1114 while (i > 0) {
1115 *str++ = tab_hex[guid[0] >> 4];
1116 *str++ = tab_hex[guid[0] & 15];
1117 guid++;
1118 i--;
1119 }
1120 *str = 0;
1121 }
1122
1123
1124 static const char * guid_names[] = {
1125 "error",
1126 /* base ASF objects */
1127 "header",
1128 "data",
1129 "simple index",
1130 "index",
1131 "media object index",
1132 "timecode index",
1133 /* header ASF objects */
1134 "file properties",
1135 "stream header",
1136 "header extension",
1137 "codec list",
1138 "script command",
1139 "marker",
1140 "bitrate mutual exclusion",
1141 "error correction",
1142 "content description",
1143 "extended content description",
1144 "stream bitrate properties", /* (http://get.to/sdp) */
1145 "extended content encryption",
1146 "padding",
1147 /* stream properties object stream type */
1148 "audio media",
1149 "video media",
1150 "command media",
1151 "JFIF media (JPEG)",
1152 "Degradable JPEG media",
1153 "File Transfer media",
1154 "Binary media",
1155 /* stream properties object error correction */
1156 "no error correction",
1157 "audio spread",
1158 /* mutual exclusion object exlusion type */
1159 "mutex bitrate",
1160 "mutex unknown",
1161 /* header extension */
1162 "reserved_1",
1163 /* script command */
1164 "reserved script command",
1165 /* marker object */
1166 "reserved marker",
1167 /* various */
1168 "audio conceal none",
1169 "codec comment1 header",
1170 "asf 2.0 header",
1171 /* header extension GUIDs */
1172 "extended stream properties",
1173 "advanced mutual exclusion",
1174 "group mutual exclusion",
1175 "stream prioritization",
1176 "bandwidth sharing",
1177 "language list",
1178 "metadata",
1179 "metadata library",
1180 "index parameters",
1181 "media object index parameters",
1182 "timecode index parameters",
1183 "advanced content encryption",
1184 /* exotic stuff */
1185 "compatibility",
1186 };
1187
asf_guid_name(asf_guid_t num)1188 const char *asf_guid_name (asf_guid_t num) {
1189 if (num >= GUID_END)
1190 num = GUID_ERROR;
1191 return guid_names[num];
1192 }
1193
1194