asfextractor.c

Go to the documentation of this file.
00001 /*
00002      This file is part of libextractor.
00003      (C) 2002, 2003 Vidyut Samanta and Christian Grothoff
00004 
00005      libextractor is free software; you can redistribute it and/or modify
00006      it under the terms of the GNU General Public License as published
00007      by the Free Software Foundation; either version 2, or (at your
00008      option) any later version.
00009 
00010      libextractor is distributed in the hope that it will be useful, but
00011      WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      General Public License for more details.
00014 
00015      You should have received a copy of the GNU General Public License
00016      along with libextractor; see the file COPYING.  If not, write to the
00017      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018      Boston, MA 02111-1307, USA.
00019  */
00020 
00021 /*
00022  * This file is based on demux_asf from the xine project (copyright follows).
00023  *
00024  * Copyright (C) 2000-2002 the xine project
00025  *
00026  * This file is part of xine, a free video player.
00027  *
00028  * xine is free software; you can redistribute it and/or modify
00029  * it under the terms of the GNU General Public License as published by
00030  * the Free Software Foundation; either version 2 of the License, or
00031  * (at your option) any later version.
00032  *
00033  * xine is distributed in the hope that it will be useful,
00034  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00035  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00036  * GNU General Public License for more details.
00037  *
00038  * You should have received a copy of the GNU General Public License
00039  * along with this program; if not, write to the Free Software
00040  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00041  *
00042  * $Id: asfextractor.c,v 1.6 2004/10/05 20:02:08 grothoff Exp $
00043  *
00044  * demultiplexer for asf streams
00045  *
00046  * based on ffmpeg's
00047  * ASF compatible encoder and decoder.
00048  * Copyright (c) 2000, 2001 Gerard Lantau.
00049  *
00050  * GUID list from avifile
00051  * some other ideas from MPlayer
00052  */
00053 
00054 #include "platform.h"
00055 #include "extractor.h"
00056 
00057 #define CODEC_TYPE_AUDIO       0
00058 #define CODEC_TYPE_VIDEO       1
00059 #define CODEC_TYPE_CONTROL     2
00060 #define MAX_NUM_STREAMS       23
00061 
00062 #define DEFRAG_BUFSIZE    65536
00063 #define DEMUX_START 1
00064 #define DEMUX_FINISHED 0
00065 
00066 
00067 /*
00068  * define asf GUIDs (list from avifile)
00069  */
00070 #define GUID_ERROR                              0
00071 
00072     /* base ASF objects */
00073 #define GUID_ASF_HEADER                         1
00074 #define GUID_ASF_DATA                           2
00075 #define GUID_ASF_SIMPLE_INDEX                   3
00076 
00077     /* header ASF objects */
00078 #define GUID_ASF_FILE_PROPERTIES                4
00079 #define GUID_ASF_STREAM_PROPERTIES              5
00080 #define GUID_ASF_STREAM_BITRATE_PROPERTIES      6
00081 #define GUID_ASF_CONTENT_DESCRIPTION            7
00082 #define GUID_ASF_EXTENDED_CONTENT_ENCRYPTION    8
00083 #define GUID_ASF_SCRIPT_COMMAND                 9
00084 #define GUID_ASF_MARKER                        10
00085 #define GUID_ASF_HEADER_EXTENSION              11
00086 #define GUID_ASF_BITRATE_MUTUAL_EXCLUSION      12
00087 #define GUID_ASF_CODEC_LIST                    13
00088 #define GUID_ASF_EXTENDED_CONTENT_DESCRIPTION  14
00089 #define GUID_ASF_ERROR_CORRECTION              15
00090 #define GUID_ASF_PADDING                       16
00091 
00092     /* stream properties object stream type */
00093 #define GUID_ASF_AUDIO_MEDIA                   17
00094 #define GUID_ASF_VIDEO_MEDIA                   18
00095 #define GUID_ASF_COMMAND_MEDIA                 19
00096 
00097     /* stream properties object error correction type */
00098 #define GUID_ASF_NO_ERROR_CORRECTION           20
00099 #define GUID_ASF_AUDIO_SPREAD                  21
00100 
00101     /* mutual exclusion object exlusion type */
00102 #define GUID_ASF_MUTEX_BITRATE                 22
00103 #define GUID_ASF_MUTEX_UKNOWN                  23
00104 
00105     /* header extension */
00106 #define GUID_ASF_RESERVED_1                    24
00107 
00108     /* script command */
00109 #define GUID_ASF_RESERVED_SCRIPT_COMMNAND      25
00110 
00111     /* marker object */
00112 #define GUID_ASF_RESERVED_MARKER               26
00113 
00114     /* various */
00115 /*
00116 #define GUID_ASF_HEAD2                         27
00117 */
00118 #define GUID_ASF_AUDIO_CONCEAL_NONE            27
00119 #define GUID_ASF_CODEC_COMMENT1_HEADER         28
00120 #define GUID_ASF_2_0_HEADER                    29
00121 
00122 #define GUID_END                               30
00123 
00124 
00125 /* asf stream types */
00126 #define ASF_STREAM_TYPE_UNKNOWN  0
00127 #define ASF_STREAM_TYPE_AUDIO    1
00128 #define ASF_STREAM_TYPE_VIDEO    2
00129 #define ASF_STREAM_TYPE_CONTROL  3
00130 
00131 #define ASF_MAX_NUM_STREAMS     23
00132 
00133 
00134 typedef unsigned long long ext_uint64_t;
00135 typedef unsigned int ext_uint32_t;
00136 typedef unsigned short ext_uint16_t;
00137 typedef unsigned char ext_uint8_t;
00138 
00139 typedef struct
00140 {
00141   ext_uint32_t v1;
00142   ext_uint16_t v2;
00143   ext_uint16_t v3;
00144   ext_uint8_t v4[8];
00145 } LE_GUID;
00146 
00147 static const struct
00148 {
00149   const char *name;
00150   const LE_GUID guid;
00151 } guids[] =
00152 {
00153   {
00154     "error",
00155     {
00156   0x0,}},
00157     /* base ASF objects */
00158   {
00159     "header",
00160     {
00161       0x75b22630, 0x668e, 0x11cf,
00162       {
00163   0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}}},
00164   {
00165     "data",
00166     {
00167       0x75b22636, 0x668e, 0x11cf,
00168       {
00169   0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}}},
00170   {
00171     "simple index",
00172     {
00173       0x33000890, 0xe5b1, 0x11cf,
00174       {
00175   0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb}}},
00176     /* header ASF objects */
00177   {
00178     "file properties",
00179     {
00180       0x8cabdca1, 0xa947, 0x11cf,
00181       {
00182   0x8e, 0xe4, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
00183   {
00184     "stream header",
00185     {
00186       0xb7dc0791, 0xa9b7, 0x11cf,
00187       {
00188   0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
00189   {
00190     "stream bitrate properties",        /* (http://get.to/sdp) */
00191     {
00192       0x7bf875ce, 0x468d, 0x11d1,
00193       {
00194   0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2}}},
00195   {
00196     "content description",
00197     {
00198       0x75b22633, 0x668e, 0x11cf,
00199       {
00200   0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}}},
00201   {
00202     "extended content encryption",
00203     {
00204       0x298ae614, 0x2622, 0x4c17,
00205       {
00206   0xb9, 0x35, 0xda, 0xe0, 0x7e, 0xe9, 0x28, 0x9c}}},
00207   {
00208     "script command",
00209     {
00210       0x1efb1a30, 0x0b62, 0x11d0,
00211       {
00212   0xa3, 0x9b, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
00213   {
00214     "marker",
00215     {
00216       0xf487cd01, 0xa951, 0x11cf,
00217       {
00218   0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
00219   {
00220     "header extension",
00221     {
00222       0x5fbf03b5, 0xa92e, 0x11cf,
00223       {
00224   0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
00225   {
00226     "bitrate mutual exclusion",
00227     {
00228       0xd6e229dc, 0x35da, 0x11d1,
00229       {
00230   0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},
00231   {
00232     "codec list",
00233     {
00234       0x86d15240, 0x311d, 0x11d0,
00235       {
00236   0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
00237   {
00238     "extended content description",
00239     {
00240       0xd2d0a440, 0xe307, 0x11d2,
00241       {
00242   0x97, 0xf0, 0x00, 0xa0, 0xc9, 0x5e, 0xa8, 0x50}}},
00243   {
00244     "error correction",
00245     {
00246       0x75b22635, 0x668e, 0x11cf,
00247       {
00248   0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}}},
00249   {
00250     "padding",
00251     {
00252       0x1806d474, 0xcadf, 0x4509,
00253       {
00254   0xa4, 0xba, 0x9a, 0xab, 0xcb, 0x96, 0xaa, 0xe8}}},
00255     /* stream properties object stream type */
00256   {
00257     "audio media",
00258     {
00259       0xf8699e40, 0x5b4d, 0x11cf,
00260       {
00261   0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b}}},
00262   {
00263     "video media",
00264     {
00265       0xbc19efc0, 0x5b4d, 0x11cf,
00266       {
00267   0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b}}},
00268   {
00269     "command media",
00270     {
00271       0x59dacfc0, 0x59e6, 0x11d0,
00272       {
00273   0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
00274     /* stream properties object error correction */
00275   {
00276     "no error correction",
00277     {
00278       0x20fb5700, 0x5b55, 0x11cf,
00279       {
00280   0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b}}},
00281   {
00282     "audio spread",
00283     {
00284       0xbfc3cd50, 0x618f, 0x11cf,
00285       {
00286   0x8b, 0xb2, 0x00, 0xaa, 0x00, 0xb4, 0xe2, 0x20}}},
00287     /* mutual exclusion object exlusion type */
00288   {
00289     "mutex bitrate",
00290     {
00291       0xd6e22a01, 0x35da, 0x11d1,
00292       {
00293   0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},
00294   {
00295     "mutex unknown",
00296     {
00297       0xd6e22a02, 0x35da, 0x11d1,
00298       {
00299   0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},
00300     /* header extension */
00301   {
00302     "reserved_1",
00303     {
00304       0xabd3d211, 0xa9ba, 0x11cf,
00305       {
00306   0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65}}},
00307     /* script command */
00308   {
00309     "reserved script command",
00310     {
00311       0x4B1ACBE3, 0x100B, 0x11D0,
00312       {
00313   0xA3, 0x9B, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6}}},
00314     /* marker object */
00315   {
00316     "reserved marker",
00317     {
00318       0x4CFEDB20, 0x75F6, 0x11CF,
00319       {
00320   0x9C, 0x0F, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB}}},
00321     /* various */
00322     /* Already defined (reserved_1)
00323        { "head2",
00324        { 0xabd3d211, 0xa9ba, 0x11cf, { 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 }} },
00325      */
00326   {
00327     "audio conceal none",
00328     {
00329       0x49f1a440, 0x4ece, 0x11d0,
00330       {
00331   0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
00332   {
00333     "codec comment1 header",
00334     {
00335       0x86d15241, 0x311d, 0x11d0,
00336       {
00337   0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6}}},
00338   {
00339     "asf 2.0 header",
00340     {
00341       0xd6e229d1, 0x35da, 0x11d1,
00342       {
00343 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe}}},};
00344 
00345 typedef struct
00346 {
00347   int num;
00348   int seq;
00349 
00350   int frag_offset;
00351   int64_t timestamp;
00352   int ts_per_kbyte;
00353   int defrag;
00354 
00355   ext_uint32_t buf_type;
00356   int stream_id;
00357 
00358   ext_uint8_t *buffer;
00359 } asf_stream_t;
00360 
00361 typedef struct demux_asf_s
00362 {
00363   /* pointer to the stream data */
00364   char *input;
00365   /* current position in stream */
00366   size_t inputPos;
00367   size_t inputLen;
00368 
00369   int keyframe_found;
00370 
00371   int seqno;
00372   ext_uint32_t packet_size;
00373   ext_uint8_t packet_flags;
00374   ext_uint32_t data_size;
00375 
00376   ext_uint32_t bitrates[MAX_NUM_STREAMS];
00377   int num_streams;
00378   int num_audio_streams;
00379   int num_video_streams;
00380   int audio_stream;
00381   int video_stream;
00382   int audio_stream_id;
00383   int video_stream_id;
00384   int control_stream_id;
00385 
00386   ext_uint16_t wavex[1024];
00387   int wavex_size;
00388 
00389   char title[512];
00390   char author[512];
00391   char copyright[512];
00392   char comment[512];
00393 
00394   ext_uint32_t length, rate;
00395 
00396   /* packet filling */
00397   int packet_size_left;
00398 
00399   /* frame rate calculations, discontinuity detection */
00400 
00401   int64_t last_pts[2];
00402   int32_t frame_duration;
00403   int send_newpts;
00404   int64_t last_frame_pts;
00405 
00406   /* only for reading */
00407   ext_uint32_t packet_padsize;
00408   int nb_frames;
00409   ext_uint8_t frame_flag;
00410   ext_uint8_t segtype;
00411   int frame;
00412 
00413   int status;
00414 
00415   /* byte reordering from audio streams */
00416   int reorder_h;
00417   int reorder_w;
00418   int reorder_b;
00419 
00420   off_t header_size;
00421   int buf_flag_seek;
00422 
00423   /* first packet position */
00424   int64_t first_packet_pos;
00425 
00426   int reference_mode;
00427 } demux_asf_t;
00428 
00429 static int
00430 readBuf (demux_asf_t * this, void *buf, int len)
00431 {
00432   int min;
00433 
00434   min = len;
00435   if (this->inputLen - this->inputPos < min)
00436     min = this->inputLen - this->inputPos;
00437   memcpy (buf, &this->input[this->inputPos], min);
00438   this->inputPos += min;
00439   return min;
00440 }
00441 
00442 static ext_uint8_t
00443 get_byte (demux_asf_t * this)
00444 {
00445   ext_uint8_t buf;
00446   int i;
00447 
00448   i = readBuf (this, &buf, 1);
00449   if (i != 1)
00450     this->status = DEMUX_FINISHED;
00451   return buf;
00452 }
00453 
00454 static ext_uint16_t
00455 get_le16 (demux_asf_t * this)
00456 {
00457   ext_uint8_t buf[2];
00458   int i;
00459 
00460   i = readBuf (this, buf, 2);
00461   if (i != 2)
00462     this->status = DEMUX_FINISHED;
00463   return buf[0] | (buf[1] << 8);
00464 }
00465 
00466 static ext_uint32_t
00467 get_le32 (demux_asf_t * this)
00468 {
00469   ext_uint8_t buf[4];
00470   int i;
00471 
00472   i = readBuf (this, buf, 4);
00473   if (i != 4)
00474     this->status = DEMUX_FINISHED;
00475   return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
00476 }
00477 
00478 static ext_uint64_t
00479 get_le64 (demux_asf_t * this)
00480 {
00481   ext_uint8_t buf[8];
00482   int i;
00483 
00484   i = readBuf (this, buf, 8);
00485   if (i != 8)
00486     this->status = DEMUX_FINISHED;
00487   return (ext_uint64_t) buf[0]
00488     | ((ext_uint64_t) buf[1] << 8)
00489     | ((ext_uint64_t) buf[2] << 16)
00490     | ((ext_uint64_t) buf[3] << 24)
00491     | ((ext_uint64_t) buf[4] << 32)
00492     | ((ext_uint64_t) buf[5] << 40)
00493     | ((ext_uint64_t) buf[6] << 48) | ((ext_uint64_t) buf[7] << 54);
00494 }
00495 
00496 static int
00497 get_guid (demux_asf_t * this)
00498 {
00499   int i;
00500   LE_GUID g;
00501 
00502   g.v1 = get_le32 (this);
00503   g.v2 = get_le16 (this);
00504   g.v3 = get_le16 (this);
00505   for (i = 0; i < 8; i++)
00506     g.v4[i] = get_byte (this);
00507   if (this->status == DEMUX_FINISHED)
00508     return GUID_ERROR;
00509   for (i = 1; i < GUID_END; i++)
00510     if (!memcmp (&g, &guids[i].guid, sizeof (LE_GUID)))
00511       return i;
00512 
00513   return GUID_ERROR;
00514 }
00515 
00516 static void
00517 get_str16_nolen (demux_asf_t * this, int len, char *buf, int buf_size)
00518 {
00519 
00520   int c;
00521   char *q;
00522 
00523   q = buf;
00524   while (len > 0)
00525     {
00526       c = get_le16 (this);
00527       if ((q - buf) < buf_size - 1)
00528         *q++ = c;
00529       len -= 2;
00530     }
00531   *q = '\0';
00532 }
00533 
00534 static int
00535 asf_read_header (demux_asf_t * this)
00536 {
00537   int guid;
00538   ext_uint64_t gsize;
00539 
00540   guid = get_guid (this);
00541   if (guid != GUID_ASF_HEADER)
00542     return 0;
00543   get_le64 (this);
00544   get_le32 (this);
00545   get_byte (this);
00546   get_byte (this);
00547 
00548   while (this->status != DEMUX_FINISHED)
00549     {
00550       guid = get_guid (this);
00551       gsize = get_le64 (this);
00552 
00553       if (gsize < 24)
00554         goto fail;
00555 
00556       switch (guid)
00557         {
00558         case GUID_ASF_FILE_PROPERTIES:
00559           {
00560             ext_uint64_t start_time, end_time;
00561 
00562             guid = get_guid (this);
00563             get_le64 (this);    /* file size */
00564             get_le64 (this);    /* file time */
00565             get_le64 (this);    /* nb_packets */
00566 
00567             end_time = get_le64 (this);
00568 
00569             this->length = get_le64 (this) / 10000;
00570             if (this->length)
00571               this->rate = this->inputLen / (this->length / 1000);
00572             else
00573               this->rate = 0;
00574 
00575 
00576             start_time = get_le32 (this);       /* start timestamp in 1/1000 s */
00577 
00578             get_le32 (this);    /* unknown */
00579             get_le32 (this);    /* min size */
00580             this->packet_size = get_le32 (this);        /* max size */
00581             get_le32 (this);    /* max bitrate */
00582             get_le32 (this);
00583           }
00584           break;
00585 
00586         case (GUID_ASF_STREAM_PROPERTIES):
00587           {
00588             int type;
00589             ext_uint32_t total_size, stream_data_size;
00590             ext_uint16_t stream_id;
00591             ext_uint64_t pos1, pos2;
00592             pos1 = this->inputPos;
00593 
00594             guid = get_guid (this);
00595             switch (guid)
00596               {
00597               case GUID_ASF_AUDIO_MEDIA:
00598                 type = CODEC_TYPE_AUDIO;
00599                 break;
00600 
00601               case GUID_ASF_VIDEO_MEDIA:
00602                 type = CODEC_TYPE_VIDEO;
00603                 break;
00604 
00605               case GUID_ASF_COMMAND_MEDIA:
00606                 type = CODEC_TYPE_CONTROL;
00607                 break;
00608 
00609               default:
00610                 goto fail;
00611               }
00612 
00613             guid = get_guid (this);
00614             get_le64 (this);
00615             total_size = get_le32 (this);
00616             if (total_size > sizeof (this->wavex))
00617               goto fail;
00618             stream_data_size = get_le32 (this);
00619             stream_id = get_le16 (this);        /* stream id */
00620             get_le32 (this);
00621 
00622             if (type == CODEC_TYPE_AUDIO)
00623               {
00624                 ext_uint8_t buffer[6];
00625 
00626                 readBuf (this, (ext_uint8_t *) this->wavex, total_size);
00627                 if (guid == GUID_ASF_AUDIO_SPREAD)
00628                   {
00629                     readBuf (this, buffer, 6);
00630                     this->reorder_h = buffer[0];
00631                     this->reorder_w = (buffer[2] << 8) | buffer[1];
00632                     this->reorder_b = (buffer[4] << 8) | buffer[3];
00633                     this->reorder_w /= this->reorder_b;
00634                   }
00635                 else
00636                   {
00637                     this->reorder_b = this->reorder_h = this->reorder_w = 1;
00638                   }
00639 
00640                 this->wavex_size = total_size;  /* 18 + this->wavex[8]; */
00641                 this->num_audio_streams++;
00642               }
00643             else if (type == CODEC_TYPE_VIDEO)
00644               {
00645 
00646                 ext_uint16_t i;
00647 
00648                 get_le32 (this);        /* width */
00649                 get_le32 (this);        /* height */
00650                 get_byte (this);
00651 
00652                 i = get_le16 (this);    /* size */
00653                 this->inputPos += i;
00654                 this->num_video_streams++;
00655               }
00656             else if (type == CODEC_TYPE_CONTROL)
00657               {
00658                 this->control_stream_id = stream_id;
00659               }
00660 
00661             this->num_streams++;
00662             pos2 = this->inputPos;
00663             this->inputPos += gsize - (pos2 - pos1 + 24);
00664           }
00665           break;
00666 
00667         case GUID_ASF_DATA:
00668           goto headers_ok;
00669           break;
00670         case GUID_ASF_CONTENT_DESCRIPTION:
00671           {
00672             ext_uint16_t len1, len2, len3, len4, len5;
00673 
00674             len1 = get_le16 (this);
00675             len2 = get_le16 (this);
00676             len3 = get_le16 (this);
00677             len4 = get_le16 (this);
00678             len5 = get_le16 (this);
00679             get_str16_nolen (this, len1, this->title, sizeof (this->title));
00680             get_str16_nolen (this, len2, this->author, sizeof (this->author));
00681             get_str16_nolen (this, len3, this->copyright,
00682                              sizeof (this->copyright));
00683             get_str16_nolen (this, len4, this->comment,
00684                              sizeof (this->comment));
00685             this->inputPos += len5;
00686           }
00687           break;
00688 
00689         case GUID_ASF_STREAM_BITRATE_PROPERTIES:
00690           {
00691             ext_uint16_t streams, stream_id;
00692             ext_uint16_t i;
00693 
00694             streams = get_le16 (this);
00695             for (i = 0; i < streams; i++)
00696               {
00697                 stream_id = get_le16 (this);
00698                 this->bitrates[stream_id] = get_le32 (this);
00699               }
00700           }
00701           break;
00702 
00703         default:
00704           this->inputPos += gsize - 24;
00705         }
00706     }
00707 
00708 headers_ok:
00709   this->inputPos += sizeof (LE_GUID) + 10;
00710   this->packet_size_left = 0;
00711   this->first_packet_pos = this->inputPos;
00712   return 1;
00713 
00714 fail:
00715   return 0;
00716 }
00717 
00718 
00719 static struct EXTRACTOR_Keywords *
00720 addKeyword (EXTRACTOR_KeywordType type,
00721             char *keyword, struct EXTRACTOR_Keywords *next)
00722 {
00723   EXTRACTOR_KeywordList *result;
00724 
00725   if (keyword == NULL)
00726     return next;
00727   result = malloc (sizeof (EXTRACTOR_KeywordList));
00728   result->next = next;
00729   result->keyword = strdup (keyword);
00730   result->keywordType = type;
00731   return result;
00732 }
00733 
00734 
00735 /* mimetypes:
00736    video/x-ms-asf: asf: ASF stream;
00737    video/x-ms-wmv: wmv: Windows Media Video;
00738    video/x-ms-wma: wma: Windows Media Audio;
00739    application/vnd.ms-asf: asf: ASF stream;
00740    application/x-mplayer2: asf,asx,asp: mplayer2;
00741    video/x-ms-asf-plugin: asf,asx,asp: mms animation;
00742    video/x-ms-wvx: wvx: wmv metafile;
00743    video/x-ms-wax: wva: wma metafile; */
00744 struct EXTRACTOR_Keywords *
00745 libextractor_asf_extract (char *filename,
00746                           char *data,
00747                           size_t size, struct EXTRACTOR_Keywords *prev)
00748 {
00749   demux_asf_t *this;
00750 
00751   this = malloc (sizeof (demux_asf_t));
00752   memset (this, 0, sizeof (demux_asf_t));
00753   this->input = data;
00754   this->inputPos = 0;
00755   this->inputLen = size;
00756   this->status = DEMUX_START;
00757 
00758   if (0 == asf_read_header (this))
00759     {
00760       free (this);
00761       return prev;
00762     }
00763 
00764   if (strlen (this->title) > 0)
00765     prev = addKeyword (EXTRACTOR_TITLE, this->title, prev);
00766   if (strlen (this->author) > 0)
00767     prev = addKeyword (EXTRACTOR_AUTHOR, this->author, prev);
00768   if (strlen (this->comment) > 0)
00769     prev = addKeyword (EXTRACTOR_COMMENT, this->comment, prev);
00770   if (strlen (this->copyright) > 0)
00771     prev = addKeyword (EXTRACTOR_COPYRIGHT, this->copyright, prev);
00772   prev = addKeyword (EXTRACTOR_MIMETYPE, "video/x-ms-asf", prev);
00773 
00774   /* build a description from author and title */
00775   if (strlen (this->author) * strlen (this->title) > 0)
00776     {
00777       EXTRACTOR_KeywordList *keyword =
00778         malloc (sizeof (EXTRACTOR_KeywordList));
00779       char *word;
00780       int len = 3 + strlen (this->author) + strlen (this->title);
00781 
00782       word = malloc (len);
00783       word[0] = '\0';
00784       strcat (word, this->author);
00785       strcat (word, ": ");
00786       strcat (word, this->title);
00787       keyword->next = prev;
00788       keyword->keyword = word;
00789       keyword->keywordType = EXTRACTOR_DESCRIPTION;
00790       prev = keyword;
00791     }
00792   free (this);
00793   return prev;
00794 }
00795 
00796 
00797 /*  end of asfextractor.c */

Generated on Wed Nov 19 14:44:43 2008 for libextractor by  doxygen 1.5.1