aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/old/asf_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/old/asf_extractor.c')
-rw-r--r--src/plugins/old/asf_extractor.c587
1 files changed, 587 insertions, 0 deletions
diff --git a/src/plugins/old/asf_extractor.c b/src/plugins/old/asf_extractor.c
new file mode 100644
index 0000000..459af86
--- /dev/null
+++ b/src/plugins/old/asf_extractor.c
@@ -0,0 +1,587 @@
1/*
2 This file is part of libextractor.
3 (C) 2002, 2003, 2011 Vidyut Samanta and Christian Grothoff
4
5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 libextractor is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libextractor; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/*
22 * This file is based on demux_asf from the xine project (copyright follows).
23 *
24 * Copyright (C) 2000-2002 the xine project
25 *
26 * This file is part of xine, a free video player.
27 *
28 * xine is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 2 of the License, or
31 * (at your option) any later version.
32 *
33 * xine is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
37 *
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
41 *
42 * $Id: asfextractor.c,v 1.6 2004/10/05 20:02:08 grothoff Exp $
43 *
44 * demultiplexer for asf streams
45 *
46 * based on ffmpeg's
47 * ASF compatible encoder and decoder.
48 * Copyright (c) 2000, 2001 Gerard Lantau.
49 *
50 * GUID list from avifile
51 * some other ideas from MPlayer
52 */
53
54#include "platform.h"
55#include "extractor.h"
56#include "convert.h"
57#include <stdint.h>
58
59#define DEMUX_FINISHED 0
60#define DEMUX_START 1
61
62
63/*
64 * define asf GUIDs (list from avifile)
65 */
66#define GUID_ERROR 0
67#define GUID_ASF_HEADER 1
68#define GUID_ASF_DATA 2
69#define GUID_ASF_SIMPLE_INDEX 3
70#define GUID_ASF_FILE_PROPERTIES 4
71#define GUID_ASF_STREAM_PROPERTIES 5
72#define GUID_ASF_STREAM_BITRATE_PROPERTIES 6
73#define GUID_ASF_CONTENT_DESCRIPTION 7
74#define GUID_ASF_EXTENDED_CONTENT_ENCRYPTION 8
75#define GUID_ASF_SCRIPT_COMMAND 9
76#define GUID_ASF_MARKER 10
77#define GUID_ASF_HEADER_EXTENSION 11
78#define GUID_ASF_BITRATE_MUTUAL_EXCLUSION 12
79#define GUID_ASF_CODEC_LIST 13
80#define GUID_ASF_EXTENDED_CONTENT_DESCRIPTION 14
81#define GUID_ASF_ERROR_CORRECTION 15
82#define GUID_ASF_PADDING 16
83#define GUID_ASF_AUDIO_MEDIA 17
84#define GUID_ASF_VIDEO_MEDIA 18
85#define GUID_ASF_COMMAND_MEDIA 19
86#define GUID_ASF_NO_ERROR_CORRECTION 20
87#define GUID_ASF_AUDIO_SPREAD 21
88#define GUID_ASF_MUTEX_BITRATE 22
89#define GUID_ASF_MUTEX_UKNOWN 23
90#define GUID_ASF_RESERVED_1 24
91#define GUID_ASF_RESERVED_SCRIPT_COMMNAND 25
92#define GUID_ASF_RESERVED_MARKER 26
93#define GUID_ASF_AUDIO_CONCEAL_NONE 27
94#define GUID_ASF_CODEC_COMMENT1_HEADER 28
95#define GUID_ASF_2_0_HEADER 29
96
97#define GUID_END 30
98
99
100typedef struct
101{
102 uint32_t v1;
103 uint16_t v2;
104 uint16_t v3;
105 uint8_t v4[8];
106} LE_GUID;
107
108
109static const struct
110{
111 const char *name;
112 const LE_GUID guid;
113} guids[] =
114{
115 {
116 "error",
117 {
118 0x0,}},
119 /* base ASF objects */
120 {
121 "header",
122 {
123 0x75b22630, 0x668e, 0x11cf,
124 {
125 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}}},
126 {
127 "data",
128 {
129 0x75b22636, 0x668e, 0x11cf,
130 {
131 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}}},
132 {
133 "simple index",
134 {
135 0x33000890, 0xe5b1, 0x11cf,
136 {
137 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb}}},
138 /* header ASF objects */
139 {
140 "file properties",
141 {
142 0x8cabdca1, 0xa947, 0x11cf,
143 {
144 0x8e, 0xe4, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
145 {
146 "stream header",
147 {
148 0xb7dc0791, 0xa9b7, 0x11cf,
149 {
150 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
151 {
152 "stream bitrate properties", /* (http://get.to/sdp) */
153 {
154 0x7bf875ce, 0x468d, 0x11d1,
155 {
156 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2}}},
157 {
158 "content description",
159 {
160 0x75b22633, 0x668e, 0x11cf,
161 {
162 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}}},
163 {
164 "extended content encryption",
165 {
166 0x298ae614, 0x2622, 0x4c17,
167 {
168 0xb9, 0x35, 0xda, 0xe0, 0x7e, 0xe9, 0x28, 0x9c}}},
169 {
170 "script command",
171 {
172 0x1efb1a30, 0x0b62, 0x11d0,
173 {
174 0xa3, 0x9b, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
175 {
176 "marker",
177 {
178 0xf487cd01, 0xa951, 0x11cf,
179 {
180 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
181 {
182 "header extension",
183 {
184 0x5fbf03b5, 0xa92e, 0x11cf,
185 {
186 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
187 {
188 "bitrate mutual exclusion",
189 {
190 0xd6e229dc, 0x35da, 0x11d1,
191 {
192 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},
193 {
194 "codec list",
195 {
196 0x86d15240, 0x311d, 0x11d0,
197 {
198 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
199 {
200 "extended content description",
201 {
202 0xd2d0a440, 0xe307, 0x11d2,
203 {
204 0x97, 0xf0, 0x00, 0xa0, 0xc9, 0x5e, 0xa8, 0x50}}},
205 {
206 "error correction",
207 {
208 0x75b22635, 0x668e, 0x11cf,
209 {
210 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}}},
211 {
212 "padding",
213 {
214 0x1806d474, 0xcadf, 0x4509,
215 {
216 0xa4, 0xba, 0x9a, 0xab, 0xcb, 0x96, 0xaa, 0xe8}}},
217 /* stream properties object stream type */
218 {
219 "audio media",
220 {
221 0xf8699e40, 0x5b4d, 0x11cf,
222 {
223 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b}}},
224 {
225 "video media",
226 {
227 0xbc19efc0, 0x5b4d, 0x11cf,
228 {
229 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b}}},
230 {
231 "command media",
232 {
233 0x59dacfc0, 0x59e6, 0x11d0,
234 {
235 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
236 /* stream properties object error correction */
237 {
238 "no error correction",
239 {
240 0x20fb5700, 0x5b55, 0x11cf,
241 {
242 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b}}},
243 {
244 "audio spread",
245 {
246 0xbfc3cd50, 0x618f, 0x11cf,
247 {
248 0x8b, 0xb2, 0x00, 0xaa, 0x00, 0xb4, 0xe2, 0x20}}},
249 /* mutual exclusion object exlusion type */
250 {
251 "mutex bitrate",
252 {
253 0xd6e22a01, 0x35da, 0x11d1,
254 {
255 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},
256 {
257 "mutex unknown",
258 {
259 0xd6e22a02, 0x35da, 0x11d1,
260 {
261 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},
262 /* header extension */
263 {
264 "reserved_1",
265 {
266 0xabd3d211, 0xa9ba, 0x11cf,
267 {
268 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
269 /* script command */
270 {
271 "reserved script command",
272 {
273 0x4B1ACBE3, 0x100B, 0x11D0,
274 {
275 0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6}}},
276 /* marker object */
277 {
278 "reserved marker",
279 {
280 0x4CFEDB20, 0x75F6, 0x11CF,
281 {
282 0x9C, 0x0F, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB}}},
283 /* various */
284 /* Already defined (reserved_1)
285 { "head2",
286 { 0xabd3d211, 0xa9ba, 0x11cf, { 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 }} },
287 */
288 {
289 "audio conceal none",
290 {
291 0x49f1a440, 0x4ece, 0x11d0,
292 {
293 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
294 {
295 "codec comment1 header",
296 {
297 0x86d15241, 0x311d, 0x11d0,
298 {
299 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
300 {
301 "asf 2.0 header",
302 {
303 0xd6e229d1, 0x35da, 0x11d1,
304 {
3050x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},};
306
307
308struct demux_asf_s
309{
310 /* pointer to the stream data */
311 const char *input;
312 /* current position in stream */
313 size_t inputPos;
314
315 size_t inputLen;
316
317 uint32_t length;
318
319 int status;
320
321 char *title;
322 char *author;
323 char *copyright;
324 char *comment;
325 char *rating;
326};
327
328static int
329readBuf (struct demux_asf_s * this, void *buf, int len)
330{
331 int min;
332
333 min = len;
334 if (this->inputLen - this->inputPos < min)
335 min = this->inputLen - this->inputPos;
336 memcpy (buf, &this->input[this->inputPos], min);
337 this->inputPos += min;
338 return min;
339}
340
341static uint8_t
342get_byte (struct demux_asf_s * this)
343{
344 uint8_t buf;
345 int i;
346
347 i = readBuf (this, &buf, 1);
348 if (i != 1)
349 this->status = DEMUX_FINISHED;
350 return buf;
351}
352
353static uint16_t
354get_le16 (struct demux_asf_s * this)
355{
356 uint8_t buf[2];
357 int i;
358
359 i = readBuf (this, buf, 2);
360 if (i != 2)
361 this->status = DEMUX_FINISHED;
362 return buf[0] | (buf[1] << 8);
363}
364
365static uint32_t
366get_le32 (struct demux_asf_s * this)
367{
368 uint8_t buf[4];
369 int i;
370
371 i = readBuf (this, buf, 4);
372 if (i != 4)
373 this->status = DEMUX_FINISHED;
374 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
375}
376
377static uint64_t
378get_le64 (struct demux_asf_s * this)
379{
380 uint8_t buf[8];
381 int i;
382
383 i = readBuf (this, buf, 8);
384 if (i != 8)
385 this->status = DEMUX_FINISHED;
386 return (uint64_t) buf[0]
387 | ((uint64_t) buf[1] << 8)
388 | ((uint64_t) buf[2] << 16)
389 | ((uint64_t) buf[3] << 24)
390 | ((uint64_t) buf[4] << 32)
391 | ((uint64_t) buf[5] << 40)
392 | ((uint64_t) buf[6] << 48) | ((uint64_t) buf[7] << 54);
393}
394
395static int
396get_guid (struct demux_asf_s * this)
397{
398 int i;
399 LE_GUID g;
400
401 g.v1 = get_le32 (this);
402 g.v2 = get_le16 (this);
403 g.v3 = get_le16 (this);
404 for (i = 0; i < 8; i++)
405 g.v4[i] = get_byte (this);
406 if (this->status == DEMUX_FINISHED)
407 return GUID_ERROR;
408 for (i = 1; i < GUID_END; i++)
409 if (!memcmp (&g, &guids[i].guid, sizeof (LE_GUID)))
410 return i;
411
412 return GUID_ERROR;
413}
414
415
416static int
417asf_read_header (struct demux_asf_s * this)
418{
419 int guid;
420 uint64_t gsize;
421 uint16_t len1, len2, len3, len4, len5;
422
423 guid = get_guid (this);
424 if (guid != GUID_ASF_HEADER)
425 return 0;
426 get_le64 (this); /* object size */
427 get_le32 (this); /* number of header objects */
428 get_byte (this); /* reserved 1 */
429 get_byte (this); /* reserved 2 */
430 while (this->status != DEMUX_FINISHED)
431 {
432 guid = get_guid (this); /* object ID */
433 gsize = get_le64 (this); /* object size */
434 if (gsize < 24)
435 goto fail;
436 switch (guid)
437 {
438 case GUID_ASF_FILE_PROPERTIES:
439 guid = get_guid (this); /* file ID */
440 get_le64 (this); /* file size */
441 get_le64 (this); /* creation date */
442 get_le64 (this); /* nb_packets */
443 this->length = get_le64 (this); /* play duration in 100 ns units */
444 get_le64 (this); /* send duration */
445 get_le64 (this); /* preroll */
446 get_le32 (this); /* flags */
447 get_le32 (this); /* min size */
448 get_le32 (this); /* max size */
449 get_le32 (this); /* max bitrate */
450 break;
451 case GUID_ASF_DATA:
452 goto headers_ok;
453 break;
454 case GUID_ASF_CONTENT_DESCRIPTION:
455 len1 = get_le16 (this);
456 len2 = get_le16 (this);
457 len3 = get_le16 (this);
458 len4 = get_le16 (this);
459 len5 = get_le16 (this);
460 this->title = EXTRACTOR_common_convert_to_utf8 (&this->input[this->inputPos],
461 len1,
462 "UTF-16");
463 this->inputPos += len1;
464 this->author = EXTRACTOR_common_convert_to_utf8 (&this->input[this->inputPos],
465 len2,
466 "UTF-16");
467 this->inputPos += len2;
468 this->copyright = EXTRACTOR_common_convert_to_utf8 (&this->input[this->inputPos],
469 len3,
470 "UTF-16");
471 this->inputPos += len3;
472 this->comment = EXTRACTOR_common_convert_to_utf8 (&this->input[this->inputPos],
473 len4,
474 "UTF-16");
475 this->inputPos += len4;
476 this->rating = EXTRACTOR_common_convert_to_utf8 (&this->input[this->inputPos],
477 len5,
478 "UTF-16");
479 this->inputPos += len5;
480 break;
481 default:
482 this->inputPos += gsize - 24;
483 }
484 }
485
486headers_ok:
487 this->inputPos += sizeof (LE_GUID) + 10;
488 return 1;
489fail:
490 return 0;
491}
492
493
494/* mimetypes:
495 video/x-ms-asf: asf: ASF stream;
496 video/x-ms-wmv: wmv: Windows Media Video;
497 video/x-ms-wma: wma: Windows Media Audio;
498 application/vnd.ms-asf: asf: ASF stream;
499 application/x-mplayer2: asf,asx,asp: mplayer2;
500 video/x-ms-asf-plugin: asf,asx,asp: mms animation;
501 video/x-ms-wvx: wvx: wmv metafile;
502 video/x-ms-wax: wva: wma metafile; */
503
504/* mimetype = application/applefile */
505int
506EXTRACTOR_asf_extract (const char *data,
507 size_t size,
508 EXTRACTOR_MetaDataProcessor proc,
509 void *proc_cls,
510 const char *options)
511{
512 struct demux_asf_s this;
513 size_t slen;
514 char duration_str[30];
515 int ret;
516
517 memset (&this, 0, sizeof (struct demux_asf_s));
518 this.input = data;
519 this.inputLen = size;
520 this.status = DEMUX_START;
521 ret = 0;
522 if (1 == asf_read_header (&this))
523 {
524 snprintf (duration_str,
525 sizeof (duration_str),
526 "%llu ms", (unsigned long long) (this.length / 10000LL));
527 if ( ( (this.title != NULL) &&
528 (0 < (slen = strlen(this.title))) &&
529 (0 != proc (proc_cls,
530 "asf",
531 EXTRACTOR_METATYPE_TITLE,
532 EXTRACTOR_METAFORMAT_C_STRING,
533 "text/plain",
534 this.title,
535 slen + 1)) ) ||
536 ( (this.author != NULL) &&
537 (0 < (slen = strlen(this.author))) &&
538 (0 != proc (proc_cls,
539 "asf",
540 EXTRACTOR_METATYPE_AUTHOR_NAME,
541 EXTRACTOR_METAFORMAT_C_STRING,
542 "text/plain",
543 this.author,
544 slen + 1)) ) ||
545 ( (this.comment != NULL) &&
546 (0 < (slen = strlen(this.comment))) &&
547 (0 != proc (proc_cls,
548 "asf",
549 EXTRACTOR_METATYPE_COMMENT,
550 EXTRACTOR_METAFORMAT_C_STRING,
551 "text/plain",
552 this.comment,
553 slen + 1)) ) ||
554 ( (this.copyright != NULL) &&
555 (0 < (slen = strlen(this.copyright))) &&
556 (0 != proc (proc_cls,
557 "asf",
558 EXTRACTOR_METATYPE_COPYRIGHT,
559 EXTRACTOR_METAFORMAT_C_STRING,
560 "text/plain",
561 this.copyright,
562 slen + 1)) ) ||
563 (0 != proc (proc_cls,
564 "asf",
565 EXTRACTOR_METATYPE_MIMETYPE,
566 EXTRACTOR_METAFORMAT_C_STRING,
567 "text/plain",
568 "video/x-ms-asf",
569 strlen("video/x-ms-asf") + 1)) ||
570 (0 != proc (proc_cls,
571 "asf",
572 EXTRACTOR_METATYPE_DURATION,
573 EXTRACTOR_METAFORMAT_C_STRING,
574 "text/plain",
575 duration_str,
576 strlen(duration_str) + 1)) )
577 ret = 1;
578 }
579 free (this.title);
580 free (this.author);
581 free (this.copyright);
582 free (this.comment);
583 free (this.rating);
584 return ret;
585}
586
587/* end of asf_extractor.c */