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