aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/asf_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/asf_extractor.c')
-rw-r--r--src/plugins/asf_extractor.c491
1 files changed, 144 insertions, 347 deletions
diff --git a/src/plugins/asf_extractor.c b/src/plugins/asf_extractor.c
index ea8b803..459af86 100644
--- a/src/plugins/asf_extractor.c
+++ b/src/plugins/asf_extractor.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of libextractor. 2 This file is part of libextractor.
3 (C) 2002, 2003 Vidyut Samanta and Christian Grothoff 3 (C) 2002, 2003, 2011 Vidyut Samanta and Christian Grothoff
4 4
5 libextractor is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -53,28 +53,20 @@
53 53
54#include "platform.h" 54#include "platform.h"
55#include "extractor.h" 55#include "extractor.h"
56#include "convert.h"
57#include <stdint.h>
56 58
57#define CODEC_TYPE_AUDIO 0
58#define CODEC_TYPE_VIDEO 1
59#define CODEC_TYPE_CONTROL 2
60#define MAX_NUM_STREAMS 23
61
62#define DEFRAG_BUFSIZE 65536
63#define DEMUX_START 1
64#define DEMUX_FINISHED 0 59#define DEMUX_FINISHED 0
60#define DEMUX_START 1
65 61
66 62
67/* 63/*
68 * define asf GUIDs (list from avifile) 64 * define asf GUIDs (list from avifile)
69 */ 65 */
70#define GUID_ERROR 0 66#define GUID_ERROR 0
71
72 /* base ASF objects */
73#define GUID_ASF_HEADER 1 67#define GUID_ASF_HEADER 1
74#define GUID_ASF_DATA 2 68#define GUID_ASF_DATA 2
75#define GUID_ASF_SIMPLE_INDEX 3 69#define GUID_ASF_SIMPLE_INDEX 3
76
77 /* header ASF objects */
78#define GUID_ASF_FILE_PROPERTIES 4 70#define GUID_ASF_FILE_PROPERTIES 4
79#define GUID_ASF_STREAM_PROPERTIES 5 71#define GUID_ASF_STREAM_PROPERTIES 5
80#define GUID_ASF_STREAM_BITRATE_PROPERTIES 6 72#define GUID_ASF_STREAM_BITRATE_PROPERTIES 6
@@ -88,33 +80,16 @@
88#define GUID_ASF_EXTENDED_CONTENT_DESCRIPTION 14 80#define GUID_ASF_EXTENDED_CONTENT_DESCRIPTION 14
89#define GUID_ASF_ERROR_CORRECTION 15 81#define GUID_ASF_ERROR_CORRECTION 15
90#define GUID_ASF_PADDING 16 82#define GUID_ASF_PADDING 16
91
92 /* stream properties object stream type */
93#define GUID_ASF_AUDIO_MEDIA 17 83#define GUID_ASF_AUDIO_MEDIA 17
94#define GUID_ASF_VIDEO_MEDIA 18 84#define GUID_ASF_VIDEO_MEDIA 18
95#define GUID_ASF_COMMAND_MEDIA 19 85#define GUID_ASF_COMMAND_MEDIA 19
96
97 /* stream properties object error correction type */
98#define GUID_ASF_NO_ERROR_CORRECTION 20 86#define GUID_ASF_NO_ERROR_CORRECTION 20
99#define GUID_ASF_AUDIO_SPREAD 21 87#define GUID_ASF_AUDIO_SPREAD 21
100
101 /* mutual exclusion object exlusion type */
102#define GUID_ASF_MUTEX_BITRATE 22 88#define GUID_ASF_MUTEX_BITRATE 22
103#define GUID_ASF_MUTEX_UKNOWN 23 89#define GUID_ASF_MUTEX_UKNOWN 23
104
105 /* header extension */
106#define GUID_ASF_RESERVED_1 24 90#define GUID_ASF_RESERVED_1 24
107
108 /* script command */
109#define GUID_ASF_RESERVED_SCRIPT_COMMNAND 25 91#define GUID_ASF_RESERVED_SCRIPT_COMMNAND 25
110
111 /* marker object */
112#define GUID_ASF_RESERVED_MARKER 26 92#define GUID_ASF_RESERVED_MARKER 26
113
114 /* various */
115/*
116#define GUID_ASF_HEAD2 27
117*/
118#define GUID_ASF_AUDIO_CONCEAL_NONE 27 93#define GUID_ASF_AUDIO_CONCEAL_NONE 27
119#define GUID_ASF_CODEC_COMMENT1_HEADER 28 94#define GUID_ASF_CODEC_COMMENT1_HEADER 28
120#define GUID_ASF_2_0_HEADER 29 95#define GUID_ASF_2_0_HEADER 29
@@ -122,28 +97,15 @@
122#define GUID_END 30 97#define GUID_END 30
123 98
124 99
125/* asf stream types */
126#define ASF_STREAM_TYPE_UNKNOWN 0
127#define ASF_STREAM_TYPE_AUDIO 1
128#define ASF_STREAM_TYPE_VIDEO 2
129#define ASF_STREAM_TYPE_CONTROL 3
130
131#define ASF_MAX_NUM_STREAMS 23
132
133
134typedef unsigned long long ext_uint64_t;
135typedef unsigned int ext_uint32_t;
136typedef unsigned short ext_uint16_t;
137typedef unsigned char ext_uint8_t;
138
139typedef struct 100typedef struct
140{ 101{
141 ext_uint32_t v1; 102 uint32_t v1;
142 ext_uint16_t v2; 103 uint16_t v2;
143 ext_uint16_t v3; 104 uint16_t v3;
144 ext_uint8_t v4[8]; 105 uint8_t v4[8];
145} LE_GUID; 106} LE_GUID;
146 107
108
147static const struct 109static const struct
148{ 110{
149 const char *name; 111 const char *name;
@@ -342,92 +304,29 @@ static const struct
342 { 304 {
3430x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},}; 3050x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},};
344 306
345typedef struct
346{
347 int num;
348 int seq;
349
350 int frag_offset;
351 int64_t timestamp;
352 int ts_per_kbyte;
353 int defrag;
354 307
355 ext_uint32_t buf_type; 308struct demux_asf_s
356 int stream_id;
357
358 ext_uint8_t *buffer;
359} asf_stream_t;
360
361typedef struct demux_asf_s
362{ 309{
363 /* pointer to the stream data */ 310 /* pointer to the stream data */
364 const char *input; 311 const char *input;
365 /* current position in stream */ 312 /* current position in stream */
366 size_t inputPos; 313 size_t inputPos;
367 size_t inputLen;
368
369 int keyframe_found;
370
371 int seqno;
372 ext_uint32_t packet_size;
373 ext_uint8_t packet_flags;
374 ext_uint32_t data_size;
375
376 ext_uint32_t bitrates[MAX_NUM_STREAMS];
377 int num_streams;
378 int num_audio_streams;
379 int num_video_streams;
380 int audio_stream;
381 int video_stream;
382 int audio_stream_id;
383 int video_stream_id;
384 int control_stream_id;
385
386 ext_uint16_t wavex[1024];
387 int wavex_size;
388
389 char title[512];
390 char author[512];
391 char copyright[512];
392 char comment[512];
393
394 ext_uint32_t length, rate;
395 314
396 /* packet filling */ 315 size_t inputLen;
397 int packet_size_left;
398
399 /* frame rate calculations, discontinuity detection */
400
401 int64_t last_pts[2];
402 int32_t frame_duration;
403 int send_newpts;
404 int64_t last_frame_pts;
405 316
406 /* only for reading */ 317 uint32_t length;
407 ext_uint32_t packet_padsize;
408 int nb_frames;
409 ext_uint8_t frame_flag;
410 ext_uint8_t segtype;
411 int frame;
412 318
413 int status; 319 int status;
414 320
415 /* byte reordering from audio streams */ 321 char *title;
416 int reorder_h; 322 char *author;
417 int reorder_w; 323 char *copyright;
418 int reorder_b; 324 char *comment;
419 325 char *rating;
420 off_t header_size; 326};
421 int buf_flag_seek;
422
423 /* first packet position */
424 int64_t first_packet_pos;
425
426 int reference_mode;
427} demux_asf_t;
428 327
429static int 328static int
430readBuf (demux_asf_t * this, void *buf, int len) 329readBuf (struct demux_asf_s * this, void *buf, int len)
431{ 330{
432 int min; 331 int min;
433 332
@@ -439,10 +338,10 @@ readBuf (demux_asf_t * this, void *buf, int len)
439 return min; 338 return min;
440} 339}
441 340
442static ext_uint8_t 341static uint8_t
443get_byte (demux_asf_t * this) 342get_byte (struct demux_asf_s * this)
444{ 343{
445 ext_uint8_t buf; 344 uint8_t buf;
446 int i; 345 int i;
447 346
448 i = readBuf (this, &buf, 1); 347 i = readBuf (this, &buf, 1);
@@ -451,10 +350,10 @@ get_byte (demux_asf_t * this)
451 return buf; 350 return buf;
452} 351}
453 352
454static ext_uint16_t 353static uint16_t
455get_le16 (demux_asf_t * this) 354get_le16 (struct demux_asf_s * this)
456{ 355{
457 ext_uint8_t buf[2]; 356 uint8_t buf[2];
458 int i; 357 int i;
459 358
460 i = readBuf (this, buf, 2); 359 i = readBuf (this, buf, 2);
@@ -463,10 +362,10 @@ get_le16 (demux_asf_t * this)
463 return buf[0] | (buf[1] << 8); 362 return buf[0] | (buf[1] << 8);
464} 363}
465 364
466static ext_uint32_t 365static uint32_t
467get_le32 (demux_asf_t * this) 366get_le32 (struct demux_asf_s * this)
468{ 367{
469 ext_uint8_t buf[4]; 368 uint8_t buf[4];
470 int i; 369 int i;
471 370
472 i = readBuf (this, buf, 4); 371 i = readBuf (this, buf, 4);
@@ -475,26 +374,26 @@ get_le32 (demux_asf_t * this)
475 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 374 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
476} 375}
477 376
478static ext_uint64_t 377static uint64_t
479get_le64 (demux_asf_t * this) 378get_le64 (struct demux_asf_s * this)
480{ 379{
481 ext_uint8_t buf[8]; 380 uint8_t buf[8];
482 int i; 381 int i;
483 382
484 i = readBuf (this, buf, 8); 383 i = readBuf (this, buf, 8);
485 if (i != 8) 384 if (i != 8)
486 this->status = DEMUX_FINISHED; 385 this->status = DEMUX_FINISHED;
487 return (ext_uint64_t) buf[0] 386 return (uint64_t) buf[0]
488 | ((ext_uint64_t) buf[1] << 8) 387 | ((uint64_t) buf[1] << 8)
489 | ((ext_uint64_t) buf[2] << 16) 388 | ((uint64_t) buf[2] << 16)
490 | ((ext_uint64_t) buf[3] << 24) 389 | ((uint64_t) buf[3] << 24)
491 | ((ext_uint64_t) buf[4] << 32) 390 | ((uint64_t) buf[4] << 32)
492 | ((ext_uint64_t) buf[5] << 40) 391 | ((uint64_t) buf[5] << 40)
493 | ((ext_uint64_t) buf[6] << 48) | ((ext_uint64_t) buf[7] << 54); 392 | ((uint64_t) buf[6] << 48) | ((uint64_t) buf[7] << 54);
494} 393}
495 394
496static int 395static int
497get_guid (demux_asf_t * this) 396get_guid (struct demux_asf_s * this)
498{ 397{
499 int i; 398 int i;
500 LE_GUID g; 399 LE_GUID g;
@@ -513,193 +412,72 @@ get_guid (demux_asf_t * this)
513 return GUID_ERROR; 412 return GUID_ERROR;
514} 413}
515 414
516static void
517get_str16_nolen (demux_asf_t * this, int len, char *buf, int buf_size)
518{
519
520 int c;
521 char *q;
522
523 q = buf;
524 while (len > 0)
525 {
526 c = get_le16 (this);
527 if ((q - buf) < buf_size - 1)
528 *q++ = c;
529 len -= 2;
530 }
531 *q = '\0';
532}
533 415
534static int 416static int
535asf_read_header (demux_asf_t * this) 417asf_read_header (struct demux_asf_s * this)
536{ 418{
537 int guid; 419 int guid;
538 ext_uint64_t gsize; 420 uint64_t gsize;
421 uint16_t len1, len2, len3, len4, len5;
539 422
540 guid = get_guid (this); 423 guid = get_guid (this);
541 if (guid != GUID_ASF_HEADER) 424 if (guid != GUID_ASF_HEADER)
542 return 0; 425 return 0;
543 get_le64 (this); 426 get_le64 (this); /* object size */
544 get_le32 (this); 427 get_le32 (this); /* number of header objects */
545 get_byte (this); 428 get_byte (this); /* reserved 1 */
546 get_byte (this); 429 get_byte (this); /* reserved 2 */
547
548 while (this->status != DEMUX_FINISHED) 430 while (this->status != DEMUX_FINISHED)
549 { 431 {
550 guid = get_guid (this); 432 guid = get_guid (this); /* object ID */
551 gsize = get_le64 (this); 433 gsize = get_le64 (this); /* object size */
552
553 if (gsize < 24) 434 if (gsize < 24)
554 goto fail; 435 goto fail;
555
556 switch (guid) 436 switch (guid)
557 { 437 {
558 case GUID_ASF_FILE_PROPERTIES: 438 case GUID_ASF_FILE_PROPERTIES:
559 { 439 guid = get_guid (this); /* file ID */
560 ext_uint64_t start_time, end_time; 440 get_le64 (this); /* file size */
561 441 get_le64 (this); /* creation date */
562 guid = get_guid (this); 442 get_le64 (this); /* nb_packets */
563 get_le64 (this); /* file size */ 443 this->length = get_le64 (this); /* play duration in 100 ns units */
564 get_le64 (this); /* file time */ 444 get_le64 (this); /* send duration */
565 get_le64 (this); /* nb_packets */ 445 get_le64 (this); /* preroll */
566 446 get_le32 (this); /* flags */
567 end_time = get_le64 (this); 447 get_le32 (this); /* min size */
568 448 get_le32 (this); /* max size */
569 this->length = get_le64 (this) / 10000; 449 get_le32 (this); /* max bitrate */
570 if (this->length)
571 this->rate = this->inputLen / (this->length / 1000);
572 else
573 this->rate = 0;
574
575
576 start_time = get_le32 (this); /* start timestamp in 1/1000 s */
577
578 get_le32 (this); /* unknown */
579 get_le32 (this); /* min size */
580 this->packet_size = get_le32 (this); /* max size */
581 get_le32 (this); /* max bitrate */
582 get_le32 (this);
583 }
584 break; 450 break;
585
586 case (GUID_ASF_STREAM_PROPERTIES):
587 {
588 int type;
589 ext_uint32_t total_size, stream_data_size;
590 ext_uint16_t stream_id;
591 ext_uint64_t pos1, pos2;
592 pos1 = this->inputPos;
593
594 guid = get_guid (this);
595 switch (guid)
596 {
597 case GUID_ASF_AUDIO_MEDIA:
598 type = CODEC_TYPE_AUDIO;
599 break;
600
601 case GUID_ASF_VIDEO_MEDIA:
602 type = CODEC_TYPE_VIDEO;
603 break;
604
605 case GUID_ASF_COMMAND_MEDIA:
606 type = CODEC_TYPE_CONTROL;
607 break;
608
609 default:
610 goto fail;
611 }
612
613 guid = get_guid (this);
614 get_le64 (this);
615 total_size = get_le32 (this);
616 if (total_size > sizeof (this->wavex))
617 goto fail;
618 stream_data_size = get_le32 (this);
619 stream_id = get_le16 (this); /* stream id */
620 get_le32 (this);
621
622 if (type == CODEC_TYPE_AUDIO)
623 {
624 ext_uint8_t buffer[6];
625
626 readBuf (this, (ext_uint8_t *) this->wavex, total_size);
627 if (guid == GUID_ASF_AUDIO_SPREAD)
628 {
629 readBuf (this, buffer, 6);
630 this->reorder_h = buffer[0];
631 this->reorder_w = (buffer[2] << 8) | buffer[1];
632 this->reorder_b = (buffer[4] << 8) | buffer[3];
633 this->reorder_w /= this->reorder_b;
634 }
635 else
636 {
637 this->reorder_b = this->reorder_h = this->reorder_w = 1;
638 }
639
640 this->wavex_size = total_size; /* 18 + this->wavex[8]; */
641 this->num_audio_streams++;
642 }
643 else if (type == CODEC_TYPE_VIDEO)
644 {
645
646 ext_uint16_t i;
647
648 get_le32 (this); /* width */
649 get_le32 (this); /* height */
650 get_byte (this);
651
652 i = get_le16 (this); /* size */
653 this->inputPos += i;
654 this->num_video_streams++;
655 }
656 else if (type == CODEC_TYPE_CONTROL)
657 {
658 this->control_stream_id = stream_id;
659 }
660
661 this->num_streams++;
662 pos2 = this->inputPos;
663 this->inputPos += gsize - (pos2 - pos1 + 24);
664 }
665 break;
666
667 case GUID_ASF_DATA: 451 case GUID_ASF_DATA:
668 goto headers_ok; 452 goto headers_ok;
669 break; 453 break;
670 case GUID_ASF_CONTENT_DESCRIPTION: 454 case GUID_ASF_CONTENT_DESCRIPTION:
671 { 455 len1 = get_le16 (this);
672 ext_uint16_t len1, len2, len3, len4, len5; 456 len2 = get_le16 (this);
673 457 len3 = get_le16 (this);
674 len1 = get_le16 (this); 458 len4 = get_le16 (this);
675 len2 = get_le16 (this); 459 len5 = get_le16 (this);
676 len3 = get_le16 (this); 460 this->title = EXTRACTOR_common_convert_to_utf8 (&this->input[this->inputPos],
677 len4 = get_le16 (this); 461 len1,
678 len5 = get_le16 (this); 462 "UTF-16");
679 get_str16_nolen (this, len1, this->title, sizeof (this->title)); 463 this->inputPos += len1;
680 get_str16_nolen (this, len2, this->author, sizeof (this->author)); 464 this->author = EXTRACTOR_common_convert_to_utf8 (&this->input[this->inputPos],
681 get_str16_nolen (this, len3, this->copyright, 465 len2,
682 sizeof (this->copyright)); 466 "UTF-16");
683 get_str16_nolen (this, len4, this->comment, 467 this->inputPos += len2;
684 sizeof (this->comment)); 468 this->copyright = EXTRACTOR_common_convert_to_utf8 (&this->input[this->inputPos],
685 this->inputPos += len5; 469 len3,
686 } 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;
687 break; 480 break;
688
689 case GUID_ASF_STREAM_BITRATE_PROPERTIES:
690 {
691 ext_uint16_t streams, stream_id;
692 ext_uint16_t i;
693
694 streams = get_le16 (this);
695 for (i = 0; i < streams; i++)
696 {
697 stream_id = get_le16 (this);
698 this->bitrates[stream_id] = get_le32 (this);
699 }
700 }
701 break;
702
703 default: 481 default:
704 this->inputPos += gsize - 24; 482 this->inputPos += gsize - 24;
705 } 483 }
@@ -707,10 +485,7 @@ asf_read_header (demux_asf_t * this)
707 485
708headers_ok: 486headers_ok:
709 this->inputPos += sizeof (LE_GUID) + 10; 487 this->inputPos += sizeof (LE_GUID) + 10;
710 this->packet_size_left = 0;
711 this->first_packet_pos = this->inputPos;
712 return 1; 488 return 1;
713
714fail: 489fail:
715 return 0; 490 return 0;
716} 491}
@@ -734,57 +509,79 @@ EXTRACTOR_asf_extract (const char *data,
734 void *proc_cls, 509 void *proc_cls,
735 const char *options) 510 const char *options)
736{ 511{
737 demux_asf_t this; 512 struct demux_asf_s this;
738 size_t slen; 513 size_t slen;
514 char duration_str[30];
515 int ret;
739 516
740 memset (&this, 0, sizeof (demux_asf_t)); 517 memset (&this, 0, sizeof (struct demux_asf_s));
741 this.input = data; 518 this.input = data;
742 this.inputLen = size; 519 this.inputLen = size;
743 this.status = DEMUX_START; 520 this.status = DEMUX_START;
744 if (0 == asf_read_header (&this)) 521 ret = 0;
745 return 0; 522 if (1 == asf_read_header (&this))
746 523 {
747 if ( ( (0 < (slen = strlen(this.title))) && 524 snprintf (duration_str,
748 (0 != proc (proc_cls, 525 sizeof (duration_str),
749 "asf", 526 "%llu ms", (unsigned long long) (this.length / 10000LL));
750 EXTRACTOR_METATYPE_TITLE, 527 if ( ( (this.title != NULL) &&
751 EXTRACTOR_METAFORMAT_C_STRING, 528 (0 < (slen = strlen(this.title))) &&
752 "text/plain", 529 (0 != proc (proc_cls,
753 this.title, 530 "asf",
754 slen + 1)) ) || 531 EXTRACTOR_METATYPE_TITLE,
755 ( (0 < (slen = strlen(this.author))) && 532 EXTRACTOR_METAFORMAT_C_STRING,
756 (0 != proc (proc_cls, 533 "text/plain",
757 "asf", 534 this.title,
758 EXTRACTOR_METATYPE_AUTHOR_NAME, 535 slen + 1)) ) ||
759 EXTRACTOR_METAFORMAT_C_STRING, 536 ( (this.author != NULL) &&
760 "text/plain", 537 (0 < (slen = strlen(this.author))) &&
761 this.author, 538 (0 != proc (proc_cls,
762 slen + 1)) ) || 539 "asf",
763 ( (0 < (slen = strlen(this.comment))) && 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)) ) ||
764 (0 != proc (proc_cls, 563 (0 != proc (proc_cls,
765 "asf", 564 "asf",
766 EXTRACTOR_METATYPE_COMMENT, 565 EXTRACTOR_METATYPE_MIMETYPE,
767 EXTRACTOR_METAFORMAT_C_STRING, 566 EXTRACTOR_METAFORMAT_C_STRING,
768 "text/plain", 567 "text/plain",
769 this.comment, 568 "video/x-ms-asf",
770 slen + 1)) ) || 569 strlen("video/x-ms-asf") + 1)) ||
771 ( (0 < (slen = strlen(this.copyright))) &&
772 (0 != proc (proc_cls, 570 (0 != proc (proc_cls,
773 "asf", 571 "asf",
774 EXTRACTOR_METATYPE_COPYRIGHT, 572 EXTRACTOR_METATYPE_DURATION,
775 EXTRACTOR_METAFORMAT_C_STRING, 573 EXTRACTOR_METAFORMAT_C_STRING,
776 "text/plain", 574 "text/plain",
777 this.copyright, 575 duration_str,
778 slen + 1)) ) || 576 strlen(duration_str) + 1)) )
779 (0 != proc (proc_cls, 577 ret = 1;
780 "asf", 578 }
781 EXTRACTOR_METATYPE_MIMETYPE, 579 free (this.title);
782 EXTRACTOR_METAFORMAT_C_STRING, 580 free (this.author);
783 "text/plain", 581 free (this.copyright);
784 "video/x-ms-asf", 582 free (this.comment);
785 strlen("video/x-ms-asf") + 1)) ) 583 free (this.rating);
786 return 1; 584 return ret;
787 return 0;
788} 585}
789 586
790/* end of asf_extractor.c */ 587/* end of asf_extractor.c */