libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

demux_asf.c (57976B)


      1 /*
      2  * Copyright Copyright (C) 2000-2002 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-1301 USA
     19  *
     20  * $Id: demux_asf.c,v 1.1 2003/04/03 14:51:25 grothoff Exp $
     21  *
     22  * demultiplexer for asf streams
     23  *
     24  * based on ffmpeg's
     25  * ASF compatible encoder and decoder.
     26  * Copyright (c) 2000, 2001 Gerard Lantau.
     27  *
     28  * GUID list from avifile
     29  * some other ideas from MPlayer
     30  */
     31 
     32 #ifdef HAVE_CONFIG_H
     33 #include "config.h"
     34 #endif
     35 
     36 #include <stdio.h>
     37 #include <fcntl.h>
     38 #include <unistd.h>
     39 #include <string.h>
     40 #include <stdlib.h>
     41 
     42 #include "xine_internal.h"
     43 #include "demux.h"
     44 #include "xineutils.h"
     45 #include "asfheader.h"
     46 #include "xmlparser.h"
     47 
     48 /*
     49 #define LOG
     50 */
     51 
     52 #define CODEC_TYPE_AUDIO       0
     53 #define CODEC_TYPE_VIDEO       1
     54 #define CODEC_TYPE_CONTROL     2
     55 #define MAX_NUM_STREAMS       23
     56 
     57 #define DEFRAG_BUFSIZE    65536
     58 
     59 #define WRAP_THRESHOLD       5*90000
     60 
     61 #define PTS_AUDIO 0
     62 #define PTS_VIDEO 1
     63 
     64 typedef struct
     65 {
     66   int num;
     67   int seq;
     68 
     69   int frag_offset;
     70   int64_t timestamp;
     71   int ts_per_kbyte;
     72   int defrag;
     73 
     74   uint32_t buf_type;
     75   int stream_id;
     76   fifo_buffer_t *fifo;
     77 
     78   uint8_t *buffer;
     79 } asf_stream_t;
     80 
     81 typedef struct demux_asf_s
     82 {
     83   demux_plugin_t demux_plugin;
     84 
     85   xine_stream_t *stream;
     86 
     87   fifo_buffer_t *audio_fifo;
     88   fifo_buffer_t *video_fifo;
     89 
     90   input_plugin_t *input;
     91 
     92   int keyframe_found;
     93 
     94   int seqno;
     95   uint32_t packet_size;
     96   uint8_t packet_flags;
     97   uint32_t data_size;
     98 
     99   asf_stream_t streams[MAX_NUM_STREAMS];
    100   uint32_t bitrates[MAX_NUM_STREAMS];
    101   int num_streams;
    102   int num_audio_streams;
    103   int num_video_streams;
    104   int audio_stream;
    105   int video_stream;
    106   int audio_stream_id;
    107   int video_stream_id;
    108   int control_stream_id;
    109 
    110   uint16_t wavex[1024];
    111   int wavex_size;
    112 
    113   uint16_t bih[1024];
    114   int bih_size;
    115 
    116   char title[512];
    117   char author[512];
    118   char copyright[512];
    119   char comment[512];
    120 
    121   uint32_t length, rate;
    122 
    123   /* packet filling */
    124   int packet_size_left;
    125 
    126   /* frame rate calculations, discontinuity detection */
    127 
    128   int64_t last_pts[2];
    129   int32_t frame_duration;
    130   int send_newpts;
    131   int64_t last_frame_pts;
    132 
    133   /* only for reading */
    134   uint32_t packet_padsize;
    135   int nb_frames;
    136   uint8_t frame_flag;
    137   uint8_t segtype;
    138   int frame;
    139 
    140   int status;
    141 
    142   /* byte reordering from audio streams */
    143   int reorder_h;
    144   int reorder_w;
    145   int reorder_b;
    146 
    147   off_t header_size;
    148   int buf_flag_seek;
    149 
    150   /* first packet position */
    151   int64_t first_packet_pos;
    152 
    153   int reference_mode;
    154 } demux_asf_t;
    155 
    156 typedef struct
    157 {
    158 
    159   demux_class_t demux_class;
    160 
    161   /* class-wide, global variables here */
    162 
    163   xine_t *xine;
    164   config_values_t *config;
    165 } demux_asf_class_t;
    166 
    167 
    168 static uint8_t
    169 get_byte (demux_asf_t * this)
    170 {
    171 
    172   uint8_t buf;
    173   int i;
    174 
    175   i = this->input->read (this->input, &buf, 1);
    176 
    177   /* printf ("%02x ", buf); */
    178 
    179   if (i != 1)
    180     {
    181       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
    182         printf ("demux_asf: end of data\n");
    183       this->status = DEMUX_FINISHED;
    184     }
    185 
    186   return buf;
    187 }
    188 
    189 static uint16_t
    190 get_le16 (demux_asf_t * this)
    191 {
    192 
    193   uint8_t buf[2];
    194   int i;
    195 
    196   i = this->input->read (this->input, buf, 2);
    197 
    198   /* printf (" [%02x %02x] ", buf[0], buf[1]); */
    199 
    200   if (i != 2)
    201     {
    202       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
    203         printf ("demux_asf: end of data\n");
    204       this->status = DEMUX_FINISHED;
    205     }
    206 
    207   return buf[0] | (buf[1] << 8);
    208 }
    209 
    210 static uint32_t
    211 get_le32 (demux_asf_t * this)
    212 {
    213 
    214   uint8_t buf[4];
    215   int i;
    216 
    217   i = this->input->read (this->input, buf, 4);
    218 
    219   /* printf ("%02x %02x %02x %02x ", buf[0], buf[1], buf[2], buf[3]); */
    220 
    221   if (i != 4)
    222     {
    223       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
    224         printf ("demux_asf: end of data\n");
    225       this->status = DEMUX_FINISHED;
    226     }
    227 
    228   return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
    229 }
    230 
    231 static uint64_t
    232 get_le64 (demux_asf_t * this)
    233 {
    234 
    235   uint8_t buf[8];
    236   int i;
    237 
    238   i = this->input->read (this->input, buf, 8);
    239 
    240   if (i != 8)
    241     {
    242       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
    243         printf ("demux_asf: end of data\n");
    244       this->status = DEMUX_FINISHED;
    245     }
    246 
    247   return (uint64_t) buf[0]
    248     | ((uint64_t) buf[1] << 8)
    249     | ((uint64_t) buf[2] << 16)
    250     | ((uint64_t) buf[3] << 24)
    251     | ((uint64_t) buf[4] << 32)
    252     | ((uint64_t) buf[5] << 40)
    253     | ((uint64_t) buf[6] << 48) | ((uint64_t) buf[7] << 54);
    254 }
    255 
    256 static int
    257 get_guid (demux_asf_t * this)
    258 {
    259   int i;
    260   GUID g;
    261 
    262   g.v1 = get_le32 (this);
    263   g.v2 = get_le16 (this);
    264   g.v3 = get_le16 (this);
    265   for (i = 0; i < 8; i++)
    266     {
    267       g.v4[i] = get_byte (this);
    268     }
    269 
    270   for (i = 1; i < GUID_END; i++)
    271     {
    272       if (!memcmp (&g, &guids[i].guid, sizeof (GUID)))
    273         {
    274 #ifdef LOG
    275           printf ("demux_asf: GUID: %s\n", guids[i].name);
    276 #endif
    277           return i;
    278         }
    279     }
    280 
    281   if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
    282     printf ("demux_asf: unknown GUID: 0x%x, 0x%x, 0x%x, "
    283             "{ 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx, 0x%hx }\n",
    284             g.v1, g.v2, g.v3,
    285             g.v4[0], g.v4[1], g.v4[2], g.v4[3], g.v4[4], g.v4[5], g.v4[6],
    286             g.v4[7]);
    287   return GUID_ERROR;
    288 }
    289 
    290 static void
    291 get_str16_nolen (demux_asf_t * this, int len, char *buf, int buf_size)
    292 {
    293 
    294   int c;
    295   char *q;
    296 
    297   q = buf;
    298   while (len > 0)
    299     {
    300       c = get_le16 (this);
    301       if ((q - buf) < buf_size - 1)
    302         *q++ = c;
    303       len -= 2;
    304     }
    305   *q = '\0';
    306 }
    307 
    308 static void
    309 asf_send_audio_header (demux_asf_t * this, int stream)
    310 {
    311 
    312   buf_element_t *buf;
    313   xine_waveformatex *wavex = (xine_waveformatex *) this->wavex;
    314 
    315   if (!this->audio_fifo)
    316     return;
    317 
    318   buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
    319   memcpy (buf->content, this->wavex, this->wavex_size);
    320 
    321   this->stream->stream_info[XINE_STREAM_INFO_AUDIO_FOURCC] =
    322     wavex->wFormatTag;
    323 
    324 #ifdef LOG
    325   printf ("demux_asf: wavex header is %d bytes long\n", this->wavex_size);
    326 #endif
    327 
    328   buf->size = this->wavex_size;
    329   buf->type = this->streams[stream].buf_type;
    330   buf->decoder_flags = BUF_FLAG_HEADER;
    331   buf->decoder_info[1] = wavex->nSamplesPerSec;
    332   buf->decoder_info[2] = wavex->wBitsPerSample;
    333   buf->decoder_info[3] = wavex->nChannels;
    334 
    335   this->audio_fifo->put (this->audio_fifo, buf);
    336 }
    337 
    338 static unsigned long
    339 str2ulong (unsigned char *str)
    340 {
    341   return (str[0] | (str[1] << 8) | (str[2] << 16) | (str[3] << 24));
    342 }
    343 
    344 static void
    345 asf_send_video_header (demux_asf_t * this, int stream)
    346 {
    347 
    348   buf_element_t *buf;
    349   xine_bmiheader *bih = (xine_bmiheader *) this->bih;
    350 
    351   this->stream->stream_info[XINE_STREAM_INFO_VIDEO_FOURCC] =
    352     bih->biCompression;
    353 
    354   buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
    355   buf->decoder_flags = BUF_FLAG_HEADER;
    356   buf->decoder_info[1] = 3000;  /* FIXME ? */
    357   memcpy (buf->content, &this->bih, this->bih_size);
    358   buf->size = this->bih_size;
    359   buf->type = this->streams[stream].buf_type;
    360 
    361   this->video_fifo->put (this->video_fifo, buf);
    362 
    363 }
    364 
    365 static int
    366 asf_read_header (demux_asf_t * this)
    367 {
    368 
    369   int guid;
    370   uint64_t gsize;
    371 
    372   guid = get_guid (this);
    373   if (guid != GUID_ASF_HEADER)
    374     {
    375       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
    376         printf ("demux_asf: file doesn't start with an asf header\n");
    377       return 0;
    378     }
    379   get_le64 (this);
    380   get_le32 (this);
    381   get_byte (this);
    382   get_byte (this);
    383 
    384   while (this->status != DEMUX_FINISHED)
    385     {
    386       guid = get_guid (this);
    387       gsize = get_le64 (this);
    388 
    389       if (gsize < 24)
    390         goto fail;
    391 
    392       switch (guid)
    393         {
    394         case GUID_ASF_FILE_PROPERTIES:
    395           {
    396             uint64_t start_time, end_time;
    397 
    398             guid = get_guid (this);
    399             get_le64 (this);    /* file size */
    400             get_le64 (this);    /* file time */
    401             get_le64 (this);    /* nb_packets */
    402 
    403             end_time = get_le64 (this);
    404 
    405             this->length = get_le64 (this) / 10000;
    406             if (this->length)
    407               this->rate =
    408                 this->input->get_length (this->input) / (this->length / 1000);
    409             else
    410               this->rate = 0;
    411 
    412             this->stream->stream_info[XINE_STREAM_INFO_BITRATE] =
    413               this->rate * 8;
    414 
    415             start_time = get_le32 (this);       /* start timestamp in 1/1000 s */
    416 
    417             get_le32 (this);    /* unknown */
    418             get_le32 (this);    /* min size */
    419             this->packet_size = get_le32 (this);        /* max size */
    420             get_le32 (this);    /* max bitrate */
    421             get_le32 (this);
    422           }
    423           break;
    424 
    425         case (GUID_ASF_STREAM_PROPERTIES):
    426           {
    427             int type;
    428             uint32_t total_size, stream_data_size;
    429             uint16_t stream_id;
    430             uint64_t pos1, pos2;
    431             xine_bmiheader *bih = (xine_bmiheader *) this->bih;
    432             xine_waveformatex *wavex = (xine_waveformatex *) this->wavex;
    433 
    434             pos1 = this->input->get_current_pos (this->input);
    435 
    436             guid = get_guid (this);
    437             switch (guid)
    438               {
    439               case GUID_ASF_AUDIO_MEDIA:
    440                 type = CODEC_TYPE_AUDIO;
    441                 break;
    442 
    443               case GUID_ASF_VIDEO_MEDIA:
    444                 type = CODEC_TYPE_VIDEO;
    445                 break;
    446 
    447               case GUID_ASF_COMMAND_MEDIA:
    448                 type = CODEC_TYPE_CONTROL;
    449                 break;
    450 
    451               default:
    452                 goto fail;
    453               }
    454 
    455             guid = get_guid (this);
    456             get_le64 (this);
    457             total_size = get_le32 (this);
    458             stream_data_size = get_le32 (this);
    459             stream_id = get_le16 (this);        /* stream id */
    460             get_le32 (this);
    461 
    462             if (type == CODEC_TYPE_AUDIO)
    463               {
    464                 uint8_t buffer[6];
    465 
    466                 this->input->read (this->input, (uint8_t *) this->wavex,
    467                                    total_size);
    468                 xine_waveformatex_le2me ((xine_waveformatex *) this->wavex);
    469 
    470                 /*
    471                    printf ("total size: %d bytes\n", total_size);
    472                  */
    473 
    474                 /*
    475                    this->input->read (this->input, (uint8_t *) &this->wavex[9], this->wavex[8]);
    476                  */
    477                 if (guid == GUID_ASF_AUDIO_SPREAD)
    478                   {
    479                     this->input->read (this->input, buffer, 6);
    480                     this->reorder_h = buffer[0];
    481                     this->reorder_w = (buffer[2] << 8) | buffer[1];
    482                     this->reorder_b = (buffer[4] << 8) | buffer[3];
    483                     this->reorder_w /= this->reorder_b;
    484                     if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
    485                       printf
    486                         ("demux_asf: audio conceal interleave detected (%d x %d x %d)\n",
    487                          this->reorder_w, this->reorder_h, this->reorder_b);
    488                   }
    489                 else
    490                   {
    491                     this->reorder_b = this->reorder_h = this->reorder_w = 1;
    492                   }
    493 
    494                 this->wavex_size = total_size;  /* 18 + this->wavex[8]; */
    495 
    496                 this->streams[this->num_streams].buf_type =
    497                   formattag_to_buf_audio (wavex->wFormatTag);
    498                 if (!this->streams[this->num_streams].buf_type)
    499                   {
    500                     printf ("demux_asf: unknown audio type 0x%x\n",
    501                             wavex->wFormatTag);
    502                     this->streams[this->num_streams].buf_type =
    503                       BUF_AUDIO_UNKNOWN;
    504                   }
    505 
    506                 this->streams[this->num_streams].fifo = this->audio_fifo;
    507                 this->streams[this->num_streams].stream_id = stream_id;
    508                 this->streams[this->num_streams].frag_offset = 0;
    509                 this->streams[this->num_streams].seq = 0;
    510                 if (this->reorder_h > 1 && this->reorder_w > 1)
    511                   {
    512                     if (!this->streams[this->num_streams].buffer)
    513                       this->streams[this->num_streams].buffer =
    514                         malloc (DEFRAG_BUFSIZE);
    515                     this->streams[this->num_streams].defrag = 1;
    516                   }
    517                 else
    518                   this->streams[this->num_streams].defrag = 0;
    519 
    520 #ifdef LOG
    521                 printf ("demux_asf: found an audio stream id=%d \n",
    522                         stream_id);
    523 #endif
    524                 this->num_audio_streams++;
    525               }
    526             else if (type == CODEC_TYPE_VIDEO)
    527               {
    528 
    529                 uint16_t i;
    530 
    531                 get_le32 (this);        /* width */
    532                 get_le32 (this);        /* height */
    533                 get_byte (this);
    534 
    535                 i = get_le16 (this);    /* size */
    536                 if (i > 0 && i < sizeof (this->bih))
    537                   {
    538                     this->bih_size = i;
    539                     this->input->read (this->input, (uint8_t *) this->bih,
    540                                        this->bih_size);
    541                     xine_bmiheader_le2me ((xine_bmiheader *) this->bih);
    542 
    543                     this->streams[this->num_streams].buf_type =
    544                       fourcc_to_buf_video (bih->biCompression);
    545                     if (!this->streams[this->num_streams].buf_type)
    546                       {
    547                         printf ("demux_asf: unknown video format %.4s\n",
    548                                 (char *) &bih->biCompression);
    549 
    550                         this->streams[this->num_streams].buf_type =
    551                           BUF_VIDEO_UNKNOWN;
    552                       }
    553 
    554                     this->streams[this->num_streams].fifo = this->video_fifo;
    555                     this->streams[this->num_streams].stream_id = stream_id;
    556                     this->streams[this->num_streams].frag_offset = 0;
    557                     this->streams[this->num_streams].defrag = 0;
    558 
    559                   }
    560                 else
    561                   printf
    562                     ("demux_asf: invalid bih_size received (%d), v_stream ignored.\n",
    563                      i);
    564 
    565 #ifdef LOG
    566                 printf
    567                   ("demux_asf: found a video stream id=%d, buf_type=%08x \n",
    568                    stream_id, this->streams[this->num_streams].buf_type);
    569 #endif
    570                 this->num_video_streams++;
    571               }
    572             else if (type == CODEC_TYPE_CONTROL)
    573               {
    574                 this->streams[this->num_streams].stream_id = stream_id;
    575                 this->control_stream_id = stream_id;
    576 
    577                 /* This code does'nt work
    578                    while (get_byte(this) != 0) {while (get_byte(this) != 0) {}}
    579                    while (get_byte(this) != 0) {while (get_byte(this) != 0) {}}
    580                  */
    581 #ifdef LOG
    582                 printf ("demux_asf: found a control stream id=%d \n",
    583                         stream_id);
    584 #endif
    585               }
    586 
    587             this->num_streams++;
    588             pos2 = this->input->get_current_pos (this->input);
    589             this->input->seek (this->input, gsize - (pos2 - pos1 + 24),
    590                                SEEK_CUR);
    591           }
    592           break;
    593 
    594         case GUID_ASF_DATA:
    595 #ifdef LOG
    596           printf ("demux_asf: found data\n");
    597 #endif
    598           goto headers_ok;
    599           break;
    600         case GUID_ASF_CONTENT_DESCRIPTION:
    601           {
    602             uint16_t len1, len2, len3, len4, len5;
    603 
    604             len1 = get_le16 (this);
    605             len2 = get_le16 (this);
    606             len3 = get_le16 (this);
    607             len4 = get_le16 (this);
    608             len5 = get_le16 (this);
    609             get_str16_nolen (this, len1, this->title, sizeof (this->title));
    610             get_str16_nolen (this, len2, this->author, sizeof (this->author));
    611             get_str16_nolen (this, len3, this->copyright,
    612                              sizeof (this->copyright));
    613             get_str16_nolen (this, len4, this->comment,
    614                              sizeof (this->comment));
    615             this->input->seek (this->input, len5, SEEK_CUR);
    616             /*
    617                } else if (url_feof(this)) {
    618                goto fail;
    619              */
    620           }
    621           break;
    622 
    623         case GUID_ASF_STREAM_BITRATE_PROPERTIES:
    624           {
    625             uint16_t streams, stream_id;
    626             uint16_t i;
    627 
    628 #ifdef LOG
    629             printf ("demux_asf: GUID stream group\n");
    630 #endif
    631 
    632             streams = get_le16 (this);
    633             for (i = 0; i < streams; i++)
    634               {
    635                 stream_id = get_le16 (this);
    636                 this->bitrates[stream_id] = get_le32 (this);
    637               }
    638           }
    639           break;
    640 
    641         default:
    642           this->input->seek (this->input, gsize - 24, SEEK_CUR);
    643         }
    644     }
    645 
    646 headers_ok:
    647   this->input->seek (this->input, sizeof (GUID) + 10, SEEK_CUR);
    648   this->packet_size_left = 0;
    649   this->first_packet_pos = this->input->get_current_pos (this->input);
    650   return 1;
    651 
    652 fail:
    653   return 0;
    654 }
    655 
    656 static void
    657 asf_reorder (demux_asf_t * this, uint8_t * src, int len)
    658 {
    659   uint8_t *dst = malloc (len);
    660   uint8_t *s2 = src;
    661   int i = 0, x, y;
    662 
    663   while (len - i >= this->reorder_h * this->reorder_w * this->reorder_b)
    664     {
    665       for (x = 0; x < this->reorder_w; x++)
    666         for (y = 0; y < this->reorder_h; y++)
    667           {
    668             memcpy (dst + i, s2 + (y * this->reorder_w + x) * this->reorder_b,
    669                     this->reorder_b);
    670             i += this->reorder_b;
    671           }
    672       s2 += this->reorder_h * this->reorder_w * this->reorder_b;
    673     }
    674 
    675   xine_fast_memcpy (src, dst, i);
    676   free (dst);
    677 }
    678 
    679 static uint32_t
    680 asf_get_packet (demux_asf_t * this)
    681 {
    682 
    683   int64_t timestamp;
    684   int duration;
    685   uint8_t ecd_flags;
    686   uint8_t buf[16];
    687   uint32_t p_hdr_size;
    688   int invalid_packet;
    689 
    690   do
    691     {
    692       ecd_flags = get_byte (this);
    693       p_hdr_size = 1;
    694       invalid_packet = 0;
    695 
    696       /* skip ecd */
    697       if (ecd_flags & 0x80)
    698         p_hdr_size += this->input->read (this->input, buf, ecd_flags & 0x0F);
    699 
    700       /* skip invalid packet */
    701       if (ecd_flags & 0x70)
    702         {
    703 #ifdef LOG
    704           printf ("demux_asf: skip invalid packet: %d\n", ecd_flags);
    705 #endif
    706           this->input->seek (this->input, this->packet_size - p_hdr_size,
    707                              SEEK_CUR);
    708           invalid_packet = 1;
    709         }
    710 
    711       if (this->status != DEMUX_OK)
    712         return 0;
    713 
    714     }
    715   while (invalid_packet);
    716 
    717   if (this->status != DEMUX_OK)
    718     return 0;
    719 
    720   this->packet_flags = get_byte (this);
    721   p_hdr_size += 1;
    722   this->segtype = get_byte (this);
    723   p_hdr_size += 1;
    724 
    725   /* packet size */
    726   switch ((this->packet_flags >> 5) & 3)
    727     {
    728     case 1:
    729       this->data_size = get_byte (this);
    730       p_hdr_size += 1;
    731       break;
    732     case 2:
    733       this->data_size = get_le16 (this);
    734       p_hdr_size += 2;
    735       break;
    736     case 3:
    737       this->data_size = get_le32 (this);
    738       p_hdr_size += 4;
    739       break;
    740     default:
    741       this->data_size = 0;
    742     }
    743 
    744   /* sequence */
    745   switch ((this->packet_flags >> 1) & 3)
    746     {
    747     case 1:
    748       get_byte (this);
    749       p_hdr_size += 1;
    750       break;
    751     case 2:
    752       get_le16 (this);
    753       p_hdr_size += 2;
    754       break;
    755     case 3:
    756       get_le32 (this);
    757       p_hdr_size += 4;
    758       break;
    759     }
    760 
    761   /* padding size */
    762   switch ((this->packet_flags >> 3) & 3)
    763     {
    764     case 1:
    765       this->packet_padsize = get_byte (this);
    766       p_hdr_size += 1;
    767       break;
    768     case 2:
    769       this->packet_padsize = get_le16 (this);
    770       p_hdr_size += 2;
    771       break;
    772     case 3:
    773       this->packet_padsize = get_le32 (this);
    774       p_hdr_size += 4;
    775       break;
    776     default:
    777       this->packet_padsize = 0;
    778     }
    779 
    780   timestamp = get_le32 (this);
    781   p_hdr_size += 4;
    782   duration = get_le16 (this);
    783   p_hdr_size += 2;
    784 
    785   if ((this->packet_flags >> 5) & 3)
    786     {
    787       /* absolute data size */
    788 #ifdef LOG
    789       printf ("demux_asf: absolute data size\n");
    790 #endif
    791       this->packet_padsize = this->packet_size - this->data_size;       /* not used */
    792     }
    793   else
    794     {
    795       /* relative data size */
    796 #ifdef LOG
    797       printf ("demux_asf: relative data size\n");
    798 #endif
    799       this->data_size = this->packet_size - this->packet_padsize;
    800     }
    801 
    802   /* this->packet_size_left = this->packet_size - p_hdr_size; */
    803   this->packet_size_left = this->data_size - p_hdr_size;
    804 #ifdef LOG
    805   printf
    806     ("demux_asf: new packet, size = %d, size_left = %d, flags = 0x%02x, padsize = %d, this->packet_size = %d\n",
    807      this->data_size, this->packet_size_left, this->packet_flags,
    808      this->packet_padsize, this->packet_size);
    809 #endif
    810 
    811   return 1;
    812 }
    813 
    814 static void
    815 hexdump (unsigned char *data, int len, xine_t * xine)
    816 {
    817   int i;
    818 
    819   for (i = 0; i < len; i++)
    820     printf ("%02x ", data[i]);
    821   printf ("\n");
    822 
    823 }
    824 
    825 /* redefine abs as macro to handle 64-bit diffs.
    826    i guess llabs may not be available everywhere */
    827 #define abs(x) ( ((x)<0) ? -(x) : (x) )
    828 
    829 static void
    830 check_newpts (demux_asf_t * this, int64_t pts, int video, int frame_end)
    831 {
    832   int64_t diff;
    833 
    834   diff = pts - this->last_pts[video];
    835 
    836   if (pts
    837       && (this->send_newpts
    838           || (this->last_pts[video] && abs (diff) > WRAP_THRESHOLD)))
    839     {
    840 
    841 #ifdef LOG
    842       printf ("demux_asf: sending newpts %lld (video = %d diff = %lld)\n",
    843               pts, video, diff);
    844 #endif
    845 
    846       if (this->buf_flag_seek)
    847         {
    848           xine_demux_control_newpts (this->stream, pts, BUF_FLAG_SEEK);
    849           this->buf_flag_seek = 0;
    850         }
    851       else
    852         {
    853           xine_demux_control_newpts (this->stream, pts, 0);
    854         }
    855 
    856       this->send_newpts = 0;
    857       this->last_pts[1 - video] = 0;
    858     }
    859 
    860   if (pts)
    861     this->last_pts[video] = pts;
    862 
    863   /*
    864    * frame rate estimation
    865    */
    866 
    867   if (pts && video && frame_end)
    868     {
    869 
    870       if (this->last_frame_pts)
    871         {
    872 
    873           diff = pts - this->last_frame_pts;
    874 
    875           if ((diff > 0) && (diff < WRAP_THRESHOLD))
    876             {
    877 #ifdef LOG
    878               printf ("demux_asf: last_frame_pts = %8lld, diff=%8lld\n",
    879                       this->last_frame_pts, diff);
    880 #endif
    881               this->frame_duration = (15 * this->frame_duration + diff) / 16;
    882 #ifdef LOG
    883               printf ("demux_asf: frame_duration is %d\n",
    884                       this->frame_duration);
    885 #endif
    886             }
    887         }
    888 
    889       this->last_frame_pts = pts;
    890     }
    891 }
    892 
    893 
    894 static void
    895 asf_send_buffer_nodefrag (demux_asf_t * this, asf_stream_t * stream,
    896                           int frag_offset, int seq,
    897                           int64_t timestamp, int frag_len, int payload_size)
    898 {
    899 
    900   buf_element_t *buf;
    901   int bufsize;
    902   int package_done;
    903 
    904   if (stream->frag_offset == 0)
    905     {
    906       /* new packet */
    907       stream->seq = seq;
    908     }
    909   else
    910     {
    911       if (seq == stream->seq && frag_offset == stream->frag_offset)
    912         {
    913           /* continuing packet */
    914         }
    915       else
    916         {
    917           /* cannot continue current packet: free it */
    918           stream->frag_offset = 0;
    919           if (frag_offset != 0)
    920             {
    921               /* cannot create new packet */
    922               this->input->seek (this->input, frag_len, SEEK_CUR);
    923               return;
    924             }
    925           else
    926             {
    927               /* create new packet */
    928               stream->seq = seq;
    929             }
    930         }
    931     }
    932 
    933 
    934   while (frag_len)
    935     {
    936       if (frag_len < stream->fifo->buffer_pool_buf_size)
    937         bufsize = frag_len;
    938       else
    939         bufsize = stream->fifo->buffer_pool_buf_size;
    940 
    941       buf = stream->fifo->buffer_pool_alloc (stream->fifo);
    942       this->input->read (this->input, buf->content, bufsize);
    943 
    944       buf->extra_info->input_pos = this->input->get_current_pos (this->input);
    945       if (this->rate)
    946         buf->extra_info->input_time =
    947           (int) ((int64_t) buf->extra_info->input_pos * 1000 / this->rate);
    948       else
    949         buf->extra_info->input_time = 0;
    950 
    951 #ifdef LOG
    952       printf ("demux_asf: input pos is %lld, input time is %d\n",
    953               buf->extra_info->input_pos, buf->extra_info->input_time);
    954 #endif
    955 
    956       buf->pts = timestamp * 90;
    957 
    958       buf->type = stream->buf_type;
    959       buf->size = bufsize;
    960       timestamp = 0;
    961 
    962       stream->frag_offset += bufsize;
    963       frag_len -= bufsize;
    964 
    965       package_done = (stream->frag_offset == payload_size);
    966 
    967       if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE)
    968         check_newpts (this, buf->pts, PTS_VIDEO, package_done);
    969       else
    970         check_newpts (this, buf->pts, PTS_AUDIO, package_done);
    971 
    972       /* test if whole packet read */
    973       if (package_done)
    974         {
    975 
    976           if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE)
    977             {
    978 
    979               buf->decoder_flags = BUF_FLAG_FRAME_END | BUF_FLAG_FRAMERATE;
    980               buf->decoder_info[0] = this->frame_duration;
    981 
    982             }
    983           else
    984             {
    985 
    986               buf->decoder_flags = BUF_FLAG_FRAME_END;
    987             }
    988 
    989           stream->frag_offset = 0;
    990 
    991         }
    992 
    993       if (!this->keyframe_found)
    994         buf->decoder_flags |= BUF_FLAG_PREVIEW;
    995 
    996 #ifdef LOG
    997       printf ("demux_asf: buffer type %08x %8d bytes, %8lld pts\n",
    998               buf->type, buf->size, buf->pts);
    999 #endif
   1000       stream->fifo->put (stream->fifo, buf);
   1001     }
   1002 }
   1003 
   1004 static void
   1005 asf_send_buffer_defrag (demux_asf_t * this, asf_stream_t * stream,
   1006                         int frag_offset, int seq,
   1007                         int64_t timestamp, int frag_len, int payload_size)
   1008 {
   1009 
   1010   buf_element_t *buf;
   1011 
   1012   /*
   1013      printf("asf_send_buffer seq=%d frag_offset=%d frag_len=%d\n",
   1014      seq, frag_offset, frag_len );
   1015    */
   1016 
   1017   if (stream->frag_offset == 0)
   1018     {
   1019       /* new packet */
   1020       stream->seq = seq;
   1021     }
   1022   else
   1023     {
   1024       if (seq == stream->seq && frag_offset == stream->frag_offset)
   1025         {
   1026           /* continuing packet */
   1027         }
   1028       else
   1029         {
   1030           /* cannot continue current packet: free it */
   1031           if (stream->frag_offset)
   1032             {
   1033               int bufsize;
   1034               uint8_t *p;
   1035 
   1036               if (stream->fifo == this->audio_fifo &&
   1037                   this->reorder_h > 1 && this->reorder_w > 1)
   1038                 {
   1039                   asf_reorder (this, stream->buffer, stream->frag_offset);
   1040                 }
   1041 
   1042               p = stream->buffer;
   1043               while (stream->frag_offset)
   1044                 {
   1045                   if (stream->frag_offset <
   1046                       stream->fifo->buffer_pool_buf_size)
   1047                     bufsize = stream->frag_offset;
   1048                   else
   1049                     bufsize = stream->fifo->buffer_pool_buf_size;
   1050 
   1051                   buf = stream->fifo->buffer_pool_alloc (stream->fifo);
   1052                   xine_fast_memcpy (buf->content, p, bufsize);
   1053 
   1054                   buf->extra_info->input_pos =
   1055                     this->input->get_current_pos (this->input);
   1056                   if (this->rate)
   1057                     buf->extra_info->input_time =
   1058                       (int) ((int64_t) buf->extra_info->input_pos * 1000 /
   1059                              this->rate);
   1060                   else
   1061                     buf->extra_info->input_time = 0;
   1062 
   1063                   buf->pts = stream->timestamp * 90 + stream->ts_per_kbyte *
   1064                     (p - stream->buffer) / 1024;
   1065 
   1066                   buf->type = stream->buf_type;
   1067                   buf->size = bufsize;
   1068 
   1069 #ifdef LOG
   1070                   printf
   1071                     ("demux_asf: buffer type %08x %8d bytes, %8lld pts\n",
   1072                      buf->type, buf->size, buf->pts);
   1073 #endif
   1074 
   1075                   stream->frag_offset -= bufsize;
   1076                   p += bufsize;
   1077 
   1078                   if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE)
   1079                     check_newpts (this, buf->pts, PTS_VIDEO,
   1080                                   !stream->frag_offset);
   1081                   else
   1082                     check_newpts (this, buf->pts, PTS_AUDIO,
   1083                                   !stream->frag_offset);
   1084 
   1085                   /* test if whole packet read */
   1086                   if (!stream->frag_offset)
   1087                     buf->decoder_flags |= BUF_FLAG_FRAME_END;
   1088 
   1089                   if (!this->keyframe_found)
   1090                     buf->decoder_flags |= BUF_FLAG_PREVIEW;
   1091 
   1092                   stream->fifo->put (stream->fifo, buf);
   1093                 }
   1094             }
   1095 
   1096           stream->frag_offset = 0;
   1097           if (frag_offset != 0)
   1098             {
   1099               /* cannot create new packet */
   1100               this->input->seek (this->input, frag_len, SEEK_CUR);
   1101               return;
   1102             }
   1103           else
   1104             {
   1105               /* create new packet */
   1106               stream->seq = seq;
   1107             }
   1108         }
   1109     }
   1110 
   1111 
   1112   if (frag_offset)
   1113     {
   1114       if (timestamp)
   1115         stream->ts_per_kbyte =
   1116           (timestamp - stream->timestamp) * 1024 * 90 / frag_offset;
   1117     }
   1118   else
   1119     {
   1120       stream->ts_per_kbyte = 0;
   1121       stream->timestamp = timestamp;
   1122     }
   1123 
   1124   if (stream->frag_offset + frag_len > DEFRAG_BUFSIZE)
   1125     {
   1126       printf ("demux_asf: buffer overflow on defrag!\n");
   1127     }
   1128   else
   1129     {
   1130       this->input->read (this->input, &stream->buffer[stream->frag_offset],
   1131                          frag_len);
   1132       stream->frag_offset += frag_len;
   1133     }
   1134 }
   1135 
   1136 static void
   1137 asf_read_packet (demux_asf_t * this)
   1138 {
   1139 
   1140   uint8_t raw_id, stream_id;
   1141   uint32_t seq, frag_offset, payload_size, frag_len, rlen;
   1142   int i;
   1143   int64_t timestamp;
   1144   asf_stream_t *stream;
   1145   uint32_t s_hdr_size = 0;
   1146   uint64_t current_pos;
   1147   uint32_t mod;
   1148   uint32_t psl;
   1149 
   1150   if ((++this->frame == (this->nb_frames & 0x3f)))
   1151     {
   1152       psl = this->packet_size_left;
   1153       current_pos = this->input->get_current_pos (this->input);
   1154       mod = (current_pos - this->first_packet_pos) % this->packet_size;
   1155       this->packet_size_left = mod ? this->packet_size - mod : 0;
   1156 
   1157 #ifdef LOG
   1158       printf
   1159         ("demux_asf: reading new packet, packet size left psl=%d, pad=%d, %d\n",
   1160          psl, this->packet_padsize, this->packet_size_left);
   1161 #endif
   1162 
   1163       if (this->packet_size_left)
   1164         this->input->seek (this->input, this->packet_size_left, SEEK_CUR);
   1165 
   1166       if (!asf_get_packet (this))
   1167         {
   1168           if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1169             printf ("demux_asf: get_packet failed\n");
   1170           this->status = DEMUX_FINISHED;
   1171           return;
   1172         }
   1173 
   1174       if (this->packet_padsize > this->packet_size)
   1175         {
   1176           /* skip packet */
   1177           if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1178             printf ("demux_asf: invalid padsize: %d\n", this->packet_padsize);
   1179           this->frame = this->nb_frames - 1;
   1180           return;
   1181         }
   1182 
   1183       /* Multiple frames */
   1184       this->frame = 0;
   1185       if (this->packet_flags & 0x01)
   1186         {
   1187           this->frame_flag = get_byte (this);
   1188           s_hdr_size += 1;
   1189           this->nb_frames = this->frame_flag & 0x3F;
   1190 #ifdef LOG
   1191           printf ("demux_asf: multiple frames %d\n", this->nb_frames);
   1192 #endif
   1193         }
   1194       else
   1195         {
   1196           this->frame_flag = 0;
   1197           this->nb_frames = 1;
   1198         }
   1199     }
   1200 
   1201   /* read segment header, find stream */
   1202   raw_id = get_byte (this);
   1203   s_hdr_size += 1;
   1204   stream_id = raw_id & 0x7f;
   1205 
   1206   stream = NULL;
   1207 #ifdef LOG
   1208   printf ("demux_asf: got raw_id =%d keyframe_found=%d\n", raw_id,
   1209           this->keyframe_found);
   1210 #endif
   1211 
   1212   if ((raw_id & 0x80) || this->keyframe_found
   1213       || (this->num_video_streams == 0))
   1214     {
   1215       for (i = 0; i < this->num_streams; i++)
   1216         {
   1217           if (this->streams[i].stream_id == stream_id &&
   1218               (stream_id == this->audio_stream_id
   1219                || stream_id == this->video_stream_id))
   1220             {
   1221               stream = &this->streams[i];
   1222             }
   1223         }
   1224 
   1225 #ifdef LOG
   1226       /* display control stream content */
   1227       if (stream_id == this->control_stream_id)
   1228         {
   1229           printf ("demux_asf: Control Stream : begin\n");
   1230           for (i = 0; i < (this->packet_size_left - s_hdr_size); i++)
   1231             {
   1232               printf ("%c", get_byte (this));
   1233             }
   1234           printf ("\ndemux_asf: Control Stream : end\n");
   1235           return;
   1236         }
   1237 #endif
   1238     }
   1239 
   1240   switch ((this->segtype >> 4) & 3)
   1241     {
   1242     case 1:
   1243       seq = get_byte (this);
   1244       s_hdr_size += 1;
   1245       break;
   1246     case 2:
   1247       seq = get_le16 (this);
   1248       s_hdr_size += 2;
   1249       break;
   1250     case 3:
   1251       seq = get_le32 (this);
   1252       s_hdr_size += 4;
   1253       break;
   1254     default:
   1255       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1256         printf ("demux_asf: seq=0\n");
   1257       seq = 0;
   1258     }
   1259 
   1260   switch ((this->segtype >> 2) & 3)
   1261     {
   1262     case 1:
   1263       frag_offset = get_byte (this);
   1264       s_hdr_size += 1;
   1265       break;
   1266     case 2:
   1267       frag_offset = get_le16 (this);
   1268       s_hdr_size += 2;
   1269       break;
   1270     case 3:
   1271       frag_offset = get_le32 (this);
   1272       s_hdr_size += 4;
   1273       break;
   1274     default:
   1275       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1276         printf ("demux_asf: frag_offset=0\n");
   1277       frag_offset = 0;
   1278     }
   1279 
   1280   /* only set keyframe_found if we have it's beginning */
   1281   if ((raw_id & 0x80) && stream && !frag_offset)
   1282     this->keyframe_found = 1;
   1283 
   1284   switch (this->segtype & 3)
   1285     {
   1286     case 1:
   1287       rlen = get_byte (this);
   1288       s_hdr_size += 1;
   1289       break;
   1290     case 2:
   1291       rlen = get_le16 (this);
   1292       s_hdr_size += 2;
   1293       break;
   1294     case 3:
   1295       rlen = get_le32 (this);
   1296       s_hdr_size += 4;
   1297       break;
   1298     default:
   1299       rlen = 0;
   1300     }
   1301 
   1302   if (rlen > this->packet_size_left)
   1303     {
   1304       /* skip packet */
   1305       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1306         printf ("demux_asf: invalid rlen %d\n", rlen);
   1307       this->frame = this->nb_frames - 1;
   1308       return;
   1309     }
   1310 
   1311 #ifdef LOG
   1312   printf
   1313     ("demux_asf: segment header, stream id %02x, frag_offset %d, flags : %02x\n",
   1314      stream_id, frag_offset, rlen);
   1315 #endif
   1316 
   1317   if (rlen == 1)
   1318     {
   1319       int data_length, data_sent = 0;
   1320 
   1321       /* multiple part segment */
   1322       timestamp = frag_offset;
   1323       get_byte (this);
   1324       s_hdr_size += 1;
   1325 
   1326       if (this->packet_flags & 0x01)
   1327         {
   1328           /* multiple frames */
   1329           switch ((this->frame_flag >> 6) & 3)
   1330             {
   1331             case 1:
   1332               data_length = get_byte (this);
   1333               s_hdr_size += 1;
   1334               break;
   1335             case 2:
   1336               data_length = get_le16 (this);
   1337               s_hdr_size += 2;
   1338               break;
   1339             case 3:
   1340               data_length = get_le32 (this);
   1341               s_hdr_size += 4;
   1342               break;
   1343             default:
   1344 #ifdef LOG
   1345               printf ("demux_asf: invalid frame_flag %d\n", this->frame_flag);
   1346 #endif
   1347               data_length = get_le16 (this);
   1348               s_hdr_size += 2;
   1349             }
   1350 
   1351 #ifdef LOG
   1352           printf ("demux_asf: reading grouping part segment, size = %d\n",
   1353                   data_length);
   1354 #endif
   1355 
   1356         }
   1357       else
   1358         {
   1359           data_length = this->packet_size_left - s_hdr_size;
   1360 #ifdef LOG
   1361           printf ("demux_asf: reading grouping single segment, size = %d\n",
   1362                   data_length);
   1363 #endif
   1364         }
   1365 
   1366       if (data_length > this->packet_size_left)
   1367         {
   1368           /* skip packet */
   1369           if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1370             printf ("demux_asf: invalid data_length\n");
   1371           this->frame = this->nb_frames - 1;
   1372           return;
   1373         }
   1374 
   1375       this->packet_size_left -= s_hdr_size;
   1376 
   1377       while (data_sent < data_length)
   1378         {
   1379           int object_length = get_byte (this);
   1380 
   1381 #ifdef LOG
   1382           printf ("demux_asf: sending grouped object, len = %d\n",
   1383                   object_length);
   1384 #endif
   1385 
   1386 
   1387           if (stream && stream->fifo)
   1388             {
   1389 #ifdef LOG
   1390               printf ("demux_asf: sending buffer of type %08x\n",
   1391                       stream->buf_type);
   1392 #endif
   1393 
   1394               if (stream->defrag)
   1395                 asf_send_buffer_defrag (this, stream, 0, seq, timestamp,
   1396                                         object_length, object_length);
   1397               else
   1398                 asf_send_buffer_nodefrag (this, stream, 0, seq, timestamp,
   1399                                           object_length, object_length);
   1400             }
   1401           else
   1402             {
   1403 #ifdef LOG
   1404               printf ("demux_asf: unhandled stream type, id %d\n", stream_id);
   1405 #endif
   1406               this->input->seek (this->input, object_length, SEEK_CUR);
   1407             }
   1408           seq++;
   1409           data_sent += object_length + 1;
   1410           this->packet_size_left -= object_length + 1;
   1411           timestamp = 0;
   1412         }
   1413 
   1414     }
   1415   else
   1416     {
   1417 
   1418       /* single part segment */
   1419       if (rlen >= 8)
   1420         {
   1421           payload_size = get_le32 (this);
   1422           s_hdr_size += 4;
   1423           timestamp = get_le32 (this);
   1424           s_hdr_size += 4;
   1425           this->input->seek (this->input, rlen - 8, SEEK_CUR);
   1426           s_hdr_size += rlen - 8;
   1427         }
   1428       else
   1429         {
   1430           if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1431             printf ("demux_asf: strange rlen %d\n", rlen);
   1432           timestamp = 0;
   1433           payload_size = 0;
   1434           this->input->seek (this->input, rlen, SEEK_CUR);
   1435           s_hdr_size += rlen;
   1436         }
   1437 
   1438       if (this->packet_flags & 0x01)
   1439         {
   1440           switch ((this->frame_flag >> 6) & 3)
   1441             {
   1442             case 1:
   1443               frag_len = get_byte (this);
   1444               s_hdr_size += 1;
   1445               break;
   1446             case 2:
   1447               frag_len = get_le16 (this);
   1448               s_hdr_size += 2;
   1449               break;
   1450             case 3:
   1451               frag_len = get_le32 (this);
   1452               s_hdr_size += 4;
   1453               break;
   1454             default:
   1455 #ifdef LOG
   1456               printf ("demux_asf: invalid frame_flag %d\n", this->frame_flag);
   1457 #endif
   1458               frag_len = get_le16 (this);
   1459               s_hdr_size += 2;
   1460             }
   1461 
   1462 #ifdef LOG
   1463           printf ("demux_asf: reading part segment, size = %d\n", frag_len);
   1464 #endif
   1465         }
   1466       else
   1467         {
   1468           frag_len = this->packet_size_left - s_hdr_size;
   1469 
   1470 #ifdef LOG
   1471           printf ("demux_asf: reading single segment, size = %d\n", frag_len);
   1472 #endif
   1473         }
   1474 
   1475       if (frag_len > this->packet_size_left)
   1476         {
   1477           /* skip packet */
   1478           if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1479             printf ("demux_asf: invalid frag_len %d\n", frag_len);
   1480           this->frame = this->nb_frames - 1;
   1481           return;
   1482         }
   1483 
   1484       if (!payload_size)
   1485         {
   1486           payload_size = frag_len;
   1487         }
   1488 
   1489       this->packet_size_left -= s_hdr_size;
   1490 
   1491       if (stream && stream->fifo)
   1492         {
   1493 
   1494 #ifdef LOG
   1495           printf ("demux_asf: sending buffer of type %08x\n",
   1496                   stream->buf_type);
   1497 #endif
   1498 
   1499           if (stream->defrag)
   1500             asf_send_buffer_defrag (this, stream, frag_offset, seq, timestamp,
   1501                                     frag_len, payload_size);
   1502           else
   1503             asf_send_buffer_nodefrag (this, stream, frag_offset, seq,
   1504                                       timestamp, frag_len, payload_size);
   1505         }
   1506       else
   1507         {
   1508 #ifdef LOG
   1509           printf ("demux_asf: unhandled stream type, id %d\n", stream_id);
   1510 #endif
   1511           this->input->seek (this->input, frag_len, SEEK_CUR);
   1512         }
   1513       this->packet_size_left -= frag_len;
   1514     }
   1515 }
   1516 
   1517 /*
   1518  * parse a m$ http reference
   1519  * format :
   1520  * [Reference]
   1521  * Ref1=http://www.blabla.com/blabla
   1522  */
   1523 static int
   1524 demux_asf_parse_http_references (demux_asf_t * this)
   1525 {
   1526   char *buf = NULL;
   1527   char *ptr;
   1528   int buf_size = 0;
   1529   int buf_used = 0;
   1530   int len;
   1531   char *href = NULL;
   1532   xine_mrl_reference_data_t *data;
   1533   xine_event_t uevent;
   1534 
   1535   /* read file to memory.
   1536    * warning: dumb code, but hopefuly ok since reference file is small */
   1537   do
   1538     {
   1539       buf_size += 1024;
   1540       buf = realloc (buf, buf_size + 1);
   1541 
   1542       len =
   1543         this->input->read (this->input, &buf[buf_used], buf_size - buf_used);
   1544 
   1545       if (len > 0)
   1546         buf_used += len;
   1547 
   1548       /* 50k of reference file? no way. something must be wrong */
   1549       if (buf_used > 50 * 1024)
   1550         break;
   1551     }
   1552   while (len > 0);
   1553 
   1554   if (buf_used)
   1555     buf[buf_used] = '\0';
   1556 
   1557   ptr = buf;
   1558   if (!strncmp (ptr, "[Reference]", 11))
   1559     {
   1560       ptr += 11;
   1561       if (*ptr == '\r')
   1562         ptr++;
   1563       if (*ptr == '\n')
   1564         ptr++;
   1565       href = strchr (ptr, '=') + 1;
   1566       *strchr (ptr, '\r') = '\0';
   1567 
   1568       /* replace http by mmsh */
   1569       if (!strncmp (href, "http", 4))
   1570         {
   1571           memcpy (href, "mmsh", 4);
   1572         }
   1573       if (this->stream->xine->verbosity >= XINE_VERBOSITY_LOG)
   1574         printf ("demux_asf: http ref: %s\n", href);
   1575       uevent.type = XINE_EVENT_MRL_REFERENCE;
   1576       uevent.stream = this->stream;
   1577       uevent.data_length = strlen (href) + sizeof (xine_mrl_reference_data_t);
   1578       data = malloc (uevent.data_length);
   1579       uevent.data = data;
   1580       strcpy (data->mrl, href);
   1581       data->alternative = 0;
   1582       xine_event_send (this->stream, &uevent);
   1583     }
   1584 
   1585   free (buf);
   1586 
   1587   this->status = DEMUX_FINISHED;
   1588   return this->status;
   1589 }
   1590 
   1591 /*
   1592  * parse a stupid ASF reference in an asx file
   1593  * format : "ASF http://www.blabla.com/blabla"
   1594  */
   1595 static int
   1596 demux_asf_parse_asf_references (demux_asf_t * this)
   1597 {
   1598   char *buf = NULL;
   1599   char *ptr;
   1600   int buf_size = 0;
   1601   int buf_used = 0;
   1602   int len;
   1603   xine_mrl_reference_data_t *data;
   1604   xine_event_t uevent;
   1605   int i;
   1606 
   1607   /* read file to memory.
   1608    * warning: dumb code, but hopefuly ok since reference file is small */
   1609   do
   1610     {
   1611       buf_size += 1024;
   1612       buf = realloc (buf, buf_size + 1);
   1613 
   1614       len =
   1615         this->input->read (this->input, &buf[buf_used], buf_size - buf_used);
   1616 
   1617       if (len > 0)
   1618         buf_used += len;
   1619 
   1620       /* 50k of reference file? no way. something must be wrong */
   1621       if (buf_used > 50 * 1024)
   1622         break;
   1623     }
   1624   while (len > 0);
   1625 
   1626   if (buf_used)
   1627     buf[buf_used] = '\0';
   1628 
   1629   ptr = buf;
   1630   if (!strncmp (ptr, "ASF ", 4))
   1631     {
   1632       ptr += 4;
   1633 
   1634       /* find the end of the string */
   1635       for (i = 4; i < buf_used; i++)
   1636         {
   1637           if ((buf[i] == ' ') || (buf[i] == '\r') || (buf[i] == '\n'))
   1638             {
   1639               buf[i] = '\0';
   1640               break;
   1641             }
   1642         }
   1643 
   1644       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1645         printf ("demux_asf: asf ref: %s\n", ptr);
   1646       uevent.type = XINE_EVENT_MRL_REFERENCE;
   1647       uevent.stream = this->stream;
   1648       uevent.data_length = strlen (ptr) + sizeof (xine_mrl_reference_data_t);
   1649       data = malloc (uevent.data_length);
   1650       uevent.data = data;
   1651       strcpy (data->mrl, ptr);
   1652       data->alternative = 0;
   1653       xine_event_send (this->stream, &uevent);
   1654     }
   1655 
   1656   free (buf);
   1657 
   1658   this->status = DEMUX_FINISHED;
   1659   return this->status;
   1660 }
   1661 
   1662 /*
   1663  * parse .asx playlist files
   1664  */
   1665 static int
   1666 demux_asf_parse_asx_references (demux_asf_t * this)
   1667 {
   1668 
   1669   char *buf = NULL;
   1670   int buf_size = 0;
   1671   int buf_used = 0;
   1672   int len;
   1673   xine_mrl_reference_data_t *data;
   1674   xine_event_t uevent;
   1675   xml_node_t *xml_tree, *asx_entry, *asx_ref;
   1676   xml_property_t *asx_prop;
   1677   int result;
   1678 
   1679 
   1680   /* read file to memory.
   1681    * warning: dumb code, but hopefuly ok since reference file is small */
   1682   do
   1683     {
   1684       buf_size += 1024;
   1685       buf = realloc (buf, buf_size + 1);
   1686 
   1687       len =
   1688         this->input->read (this->input, &buf[buf_used], buf_size - buf_used);
   1689 
   1690       if (len > 0)
   1691         buf_used += len;
   1692 
   1693       /* 50k of reference file? no way. something must be wrong */
   1694       if (buf_used > 50 * 1024)
   1695         break;
   1696     }
   1697   while (len > 0);
   1698 
   1699   if (buf_used)
   1700     buf[buf_used] = '\0';
   1701 
   1702   xml_parser_init (buf, buf_used, XML_PARSER_CASE_INSENSITIVE);
   1703   if ((result = xml_parser_build_tree (&xml_tree)) != XML_PARSER_OK)
   1704     goto __failure;
   1705 
   1706   if (!strcasecmp (xml_tree->name, "ASX"))
   1707     {
   1708 
   1709       asx_prop = xml_tree->props;
   1710 
   1711       while ((asx_prop) && (strcasecmp (asx_prop->name, "VERSION")))
   1712         asx_prop = asx_prop->next;
   1713 
   1714       if (asx_prop)
   1715         {
   1716           int version_major, version_minor = 0;
   1717 
   1718           if ((((sscanf
   1719                  (asx_prop->value, "%d.%d", &version_major,
   1720                   &version_minor)) == 2)
   1721                || ((sscanf (asx_prop->value, "%d", &version_major)) == 1))
   1722               && ((version_major == 3) && (version_minor == 0)))
   1723             {
   1724 
   1725               asx_entry = xml_tree->child;
   1726               while (asx_entry)
   1727                 {
   1728                   if ((!strcasecmp (asx_entry->name, "ENTRY")) ||
   1729                       (!strcasecmp (asx_entry->name, "ENTRYREF")))
   1730                     {
   1731                       char *href = NULL;
   1732 
   1733                       asx_ref = asx_entry->child;
   1734                       while (asx_ref)
   1735                         {
   1736 
   1737                           if (!strcasecmp (asx_ref->name, "REF"))
   1738                             {
   1739 
   1740                               for (asx_prop = asx_ref->props; asx_prop;
   1741                                    asx_prop = asx_prop->next)
   1742                                 {
   1743 
   1744                                   if (!strcasecmp (asx_prop->name, "HREF"))
   1745                                     {
   1746 
   1747                                       if (!href)
   1748                                         href = asx_prop->value;
   1749                                     }
   1750                                   if (href)
   1751                                     break;
   1752                                 }
   1753                             }
   1754                           asx_ref = asx_ref->next;
   1755                         }
   1756 
   1757                       if (href && strlen (href))
   1758                         {
   1759                           uevent.type = XINE_EVENT_MRL_REFERENCE;
   1760                           uevent.stream = this->stream;
   1761                           uevent.data_length =
   1762                             strlen (href) +
   1763                             sizeof (xine_mrl_reference_data_t);
   1764                           data = malloc (uevent.data_length);
   1765                           uevent.data = data;
   1766                           strcpy (data->mrl, href);
   1767                           data->alternative = 0;
   1768                           xine_event_send (this->stream, &uevent);
   1769                         }
   1770                       href = NULL;
   1771                     }
   1772                   asx_entry = asx_entry->next;
   1773                 }
   1774             }
   1775           else
   1776             printf ("demux_asf: Wrong ASX version: %s\n", asx_prop->value);
   1777 
   1778         }
   1779       else
   1780         printf ("demux_asf: Unable to find VERSION tag from ASX.\n");
   1781     }
   1782   else
   1783     printf ("demux_asf: Unsupported XML type: `%s'.\n", xml_tree->name);
   1784 
   1785   xml_parser_free_tree (xml_tree);
   1786 __failure:
   1787   free (buf);
   1788 
   1789   this->status = DEMUX_FINISHED;
   1790   return this->status;
   1791 }
   1792 
   1793 
   1794 /*
   1795  * xine specific functions start here
   1796  */
   1797 
   1798 static int
   1799 demux_asf_send_chunk (demux_plugin_t * this_gen)
   1800 {
   1801 
   1802   demux_asf_t *this = (demux_asf_t *) this_gen;
   1803 
   1804   switch (this->reference_mode)
   1805     {
   1806     case 1:
   1807       return demux_asf_parse_asx_references (this);
   1808       break;
   1809 
   1810     case 2:
   1811       return demux_asf_parse_http_references (this);
   1812       break;
   1813 
   1814     case 3:
   1815       return demux_asf_parse_asf_references (this);
   1816       break;
   1817 
   1818     default:
   1819       asf_read_packet (this);
   1820       return this->status;
   1821     }
   1822 }
   1823 
   1824 static void
   1825 demux_asf_dispose (demux_plugin_t * this_gen)
   1826 {
   1827 
   1828   demux_asf_t *this = (demux_asf_t *) this_gen;
   1829   int i;
   1830 
   1831   for (i = 0; i < this->num_streams; i++)
   1832     {
   1833       if (this->streams[i].buffer)
   1834         {
   1835           free (this->streams[i].buffer);
   1836           this->streams[i].buffer = NULL;
   1837         }
   1838     }
   1839 
   1840   free (this);
   1841 }
   1842 
   1843 static int
   1844 demux_asf_get_status (demux_plugin_t * this_gen)
   1845 {
   1846   demux_asf_t *this = (demux_asf_t *) this_gen;
   1847 
   1848   return this->status;
   1849 }
   1850 
   1851 static void
   1852 demux_asf_send_headers (demux_plugin_t * this_gen)
   1853 {
   1854 
   1855   demux_asf_t *this = (demux_asf_t *) this_gen;
   1856   int i;
   1857   int stream_id;
   1858   uint32_t buf_type, max_vrate, max_arate;
   1859   uint32_t bitrate = 0;
   1860 
   1861   this->video_fifo = this->stream->video_fifo;
   1862   this->audio_fifo = this->stream->audio_fifo;
   1863 
   1864   this->last_pts[0] = 0;
   1865   this->last_pts[1] = 0;
   1866   this->last_frame_pts = 0;
   1867 
   1868   this->status = DEMUX_OK;
   1869 
   1870   /* will get overridden later */
   1871   this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 0;
   1872   this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 0;
   1873 
   1874   /*
   1875    * initialize asf engine
   1876    */
   1877 
   1878   this->num_streams = 0;
   1879   this->num_audio_streams = 0;
   1880   this->num_video_streams = 0;
   1881   this->audio_stream = 0;
   1882   this->video_stream = 0;
   1883   this->audio_stream_id = 0;
   1884   this->video_stream_id = 0;
   1885   this->control_stream_id = 0;
   1886   this->packet_size = 0;
   1887   this->seqno = 0;
   1888   this->frame_duration = 3000;
   1889 
   1890   if (this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE)
   1891     this->input->seek (this->input, 0, SEEK_SET);
   1892 
   1893   if (this->reference_mode)
   1894     {
   1895       xine_demux_control_start (this->stream);
   1896       return;
   1897     }
   1898 
   1899   if (!asf_read_header (this))
   1900     {
   1901 
   1902       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1903         printf ("demux_asf: asf_read_header failed.\n");
   1904 
   1905       this->status = DEMUX_FINISHED;
   1906       return;
   1907     }
   1908   else
   1909     {
   1910 
   1911       /*
   1912        * send start buffer
   1913        */
   1914       xine_demux_control_start (this->stream);
   1915 
   1916 
   1917       this->header_size = this->input->get_current_pos (this->input);
   1918 
   1919       this->stream->meta_info[XINE_META_INFO_TITLE] = strdup (this->title);
   1920       this->stream->meta_info[XINE_META_INFO_ARTIST] = strdup (this->author);
   1921       this->stream->meta_info[XINE_META_INFO_COMMENT] =
   1922         strdup (this->comment);
   1923 
   1924 
   1925       /*  Choose the best audio and the best video stream.
   1926        *  Use the bitrate to do the choice.
   1927        */
   1928       max_vrate = 0;
   1929       max_arate = 0;
   1930       for (i = 0; i < this->num_streams; i++)
   1931         {
   1932           buf_type = (this->streams[i].buf_type & BUF_MAJOR_MASK);
   1933           stream_id = this->streams[i].stream_id;
   1934           bitrate = this->bitrates[stream_id];
   1935 
   1936           if (this->stream->xine->verbosity >= XINE_VERBOSITY_LOG)
   1937             printf ("demux_asf: stream: %d, bitrate %d bps\n", stream_id,
   1938                     bitrate);
   1939           if ((buf_type == BUF_VIDEO_BASE)
   1940               && (bitrate > max_vrate || this->video_stream_id == 0))
   1941             {
   1942 
   1943               this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 1;
   1944               this->stream->stream_info[XINE_STREAM_INFO_VIDEO_BITRATE] =
   1945                 bitrate;
   1946 
   1947               max_vrate = bitrate;
   1948               this->video_stream = i;
   1949               this->video_stream_id = stream_id;
   1950             }
   1951           else if ((buf_type == BUF_AUDIO_BASE) &&
   1952                    (bitrate > max_arate || this->audio_stream_id == 0))
   1953             {
   1954 
   1955               this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 1;
   1956               this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] =
   1957                 bitrate;
   1958 
   1959               max_arate = bitrate;
   1960               this->audio_stream = i;
   1961               this->audio_stream_id = stream_id;
   1962             }
   1963         }
   1964 
   1965       this->stream->stream_info[XINE_STREAM_INFO_BITRATE] = bitrate;
   1966 
   1967       if (this->stream->xine->verbosity >= XINE_VERBOSITY_DEBUG)
   1968         printf ("demux_asf: video stream_id: %d, audio stream_id: %d\n",
   1969                 this->video_stream_id, this->audio_stream_id);
   1970 
   1971       asf_send_audio_header (this, this->audio_stream);
   1972       asf_send_video_header (this, this->video_stream);
   1973 #ifdef LOG
   1974       printf ("demux_asf: send header done\n");
   1975 #endif
   1976 
   1977     }
   1978 
   1979   this->frame = 0;
   1980   this->nb_frames = 1;
   1981 }
   1982 
   1983 static int
   1984 demux_asf_seek (demux_plugin_t * this_gen, off_t start_pos, int start_time)
   1985 {
   1986 
   1987   demux_asf_t *this = (demux_asf_t *) this_gen;
   1988   int i;
   1989 
   1990   this->status = DEMUX_OK;
   1991 
   1992   xine_demux_flush_engine (this->stream);
   1993 
   1994   /*
   1995    * seek to start position
   1996    */
   1997   this->send_newpts = 1;
   1998   this->frame = 0;
   1999   this->nb_frames = 1;
   2000   this->packet_size_left = 0;
   2001   this->keyframe_found = (this->num_video_streams == 0);
   2002 
   2003   for (i = 0; i < this->num_streams; i++)
   2004     {
   2005       this->streams[i].frag_offset = 0;
   2006       this->streams[i].seq = 0;
   2007       this->streams[i].timestamp = 0;
   2008     }
   2009 
   2010   if (this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE)
   2011     {
   2012 
   2013       if ((!start_pos) && (start_time))
   2014         start_pos = start_time * this->rate;
   2015 
   2016       if (start_pos < this->header_size)
   2017         start_pos = this->header_size;
   2018 
   2019       this->input->seek (this->input, start_pos, SEEK_SET);
   2020 
   2021     }
   2022 
   2023   /*
   2024    * now start demuxing
   2025    */
   2026 
   2027   if (!this->stream->demux_thread_running)
   2028     {
   2029       this->buf_flag_seek = 0;
   2030     }
   2031   else
   2032     {
   2033       this->buf_flag_seek = 1;
   2034       xine_demux_flush_engine (this->stream);
   2035     }
   2036 
   2037   return this->status;
   2038 }
   2039 
   2040 static int
   2041 demux_asf_get_stream_length (demux_plugin_t * this_gen)
   2042 {
   2043 
   2044   demux_asf_t *this = (demux_asf_t *) this_gen;
   2045 
   2046   return this->length;
   2047 }
   2048 
   2049 static uint32_t
   2050 demux_asf_get_capabilities (demux_plugin_t * this_gen)
   2051 {
   2052   return DEMUX_CAP_NOCAP;
   2053 }
   2054 
   2055 static int
   2056 demux_asf_get_optional_data (demux_plugin_t * this_gen,
   2057                              void *data, int data_type)
   2058 {
   2059   return DEMUX_OPTIONAL_UNSUPPORTED;
   2060 }
   2061 
   2062 static demux_plugin_t *
   2063 open_plugin (demux_class_t * class_gen,
   2064              xine_stream_t * stream, input_plugin_t * input)
   2065 {
   2066 
   2067   demux_asf_t *this;
   2068   uint8_t buf[MAX_PREVIEW_SIZE + 1];
   2069   int len;
   2070 
   2071   switch (stream->content_detection_method)
   2072     {
   2073     case METHOD_BY_CONTENT:
   2074 
   2075       /*
   2076        * try to get a preview of the data
   2077        */
   2078       len =
   2079         input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW);
   2080       if (len == INPUT_OPTIONAL_UNSUPPORTED)
   2081         {
   2082 
   2083           if (input->get_capabilities (input) & INPUT_CAP_SEEKABLE)
   2084             {
   2085 
   2086               input->seek (input, 0, SEEK_SET);
   2087               if ((len = input->read (input, buf, 1024)) <= 0)
   2088                 return NULL;
   2089 
   2090 #ifdef LOG
   2091               printf
   2092                 ("demux_asf: PREVIEW data unavailable, but seek+read worked.\n");
   2093 #endif
   2094 
   2095             }
   2096           else
   2097             return NULL;
   2098         }
   2099 
   2100       if (memcmp (buf, &guids[GUID_ASF_HEADER].guid, sizeof (GUID)))
   2101         {
   2102           buf[len] = '\0';
   2103           if (!strstr (buf, "asx") &&
   2104               !strstr (buf, "ASX") &&
   2105               strncmp (buf, "[Reference]", 11) &&
   2106               strncmp (buf, "ASF ", 4) &&
   2107               ((buf[0] != 0x30)
   2108                || (buf[1] != 0x26) || (buf[2] != 0xb2) || (buf[3] != 0x75)))
   2109             return NULL;
   2110         }
   2111 
   2112 #ifdef LOG
   2113       printf ("demux_asf: file starts with an asf header\n");
   2114 #endif
   2115 
   2116       break;
   2117 
   2118     case METHOD_BY_EXTENSION:
   2119       {
   2120         char *ending, *mrl;
   2121 
   2122         mrl = input->get_mrl (input);
   2123 
   2124         /*
   2125          * check extension
   2126          */
   2127 
   2128         ending = strrchr (mrl, '.');
   2129 
   2130         if (!ending)
   2131           return NULL;
   2132 
   2133         if (strncasecmp (ending, ".asf", 4) &&
   2134             strncasecmp (ending, ".wmv", 4) &&
   2135             strncasecmp (ending, ".wma", 4))
   2136           {
   2137             return NULL;
   2138           }
   2139 #ifdef LOG
   2140         printf ("demux_asf: extension accepted.\n");
   2141 #endif
   2142       }
   2143       break;
   2144 
   2145     case METHOD_EXPLICIT:
   2146       break;
   2147 
   2148     default:
   2149       printf ("demux_asf: warning, unkown method %d\n",
   2150               stream->content_detection_method);
   2151       return NULL;
   2152     }
   2153 
   2154   this = xine_xmalloc (sizeof (demux_asf_t));
   2155   this->stream = stream;
   2156   this->input = input;
   2157 
   2158   /*
   2159    * check for reference stream
   2160    */
   2161   this->reference_mode = 0;
   2162   len = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW);
   2163   if ((len == INPUT_OPTIONAL_UNSUPPORTED) &&
   2164       (input->get_capabilities (input) & INPUT_CAP_SEEKABLE))
   2165     {
   2166       input->seek (input, 0, SEEK_SET);
   2167       len = input->read (input, buf, 1024);
   2168     }
   2169   if (len > 0)
   2170     {
   2171       buf[len] = '\0';
   2172       if (strstr (buf, "asx") || strstr (buf, "ASX"))
   2173         this->reference_mode = 1;
   2174       if (strstr (buf, "[Reference]"))
   2175         this->reference_mode = 2;
   2176       if (strstr (buf, "ASF "))
   2177         this->reference_mode = 3;
   2178     }
   2179 
   2180   this->demux_plugin.send_headers = demux_asf_send_headers;
   2181   this->demux_plugin.send_chunk = demux_asf_send_chunk;
   2182   this->demux_plugin.seek = demux_asf_seek;
   2183   this->demux_plugin.dispose = demux_asf_dispose;
   2184   this->demux_plugin.get_status = demux_asf_get_status;
   2185   this->demux_plugin.get_stream_length = demux_asf_get_stream_length;
   2186   this->demux_plugin.get_video_frame = NULL;
   2187   this->demux_plugin.got_video_frame_cb = NULL;
   2188   this->demux_plugin.get_capabilities = demux_asf_get_capabilities;
   2189   this->demux_plugin.get_optional_data = demux_asf_get_optional_data;
   2190   this->demux_plugin.demux_class = class_gen;
   2191 
   2192   this->status = DEMUX_FINISHED;
   2193 
   2194   return &this->demux_plugin;
   2195 }
   2196 
   2197 static char *
   2198 get_description (demux_class_t * this_gen)
   2199 {
   2200   return "ASF demux plugin";
   2201 }
   2202 
   2203 static char *
   2204 get_identifier (demux_class_t * this_gen)
   2205 {
   2206   return "ASF";
   2207 }
   2208 
   2209 static char *
   2210 get_extensions (demux_class_t * this_gen)
   2211 {
   2212   /* asx, wvx, wax are metafile or playlist */
   2213   return "asf wmv wma asx wvx wax";
   2214 }
   2215 
   2216 static char *
   2217 get_mimetypes (demux_class_t * this_gen)
   2218 {
   2219 
   2220   return "video/x-ms-asf: asf: ASF stream;"
   2221     "video/x-ms-wmv: wmv: Windows Media Video;"
   2222     "video/x-ms-wma: wma: Windows Media Audio;"
   2223     "application/vnd.ms-asf: asf: ASF stream;"
   2224     "application/x-mplayer2: asf,asx,asp: mplayer2;"
   2225     "video/x-ms-asf-plugin: asf,asx,asp: mms animation;"
   2226     "video/x-ms-wvx: wvx: wmv metafile;" "video/x-ms-wax: wva: wma metafile;";
   2227 }
   2228 
   2229 static void
   2230 class_dispose (demux_class_t * this_gen)
   2231 {
   2232 
   2233   demux_asf_class_t *this = (demux_asf_class_t *) this_gen;
   2234 
   2235   free (this);
   2236 }
   2237 
   2238 static void *
   2239 init_class (xine_t * xine, void *data)
   2240 {
   2241 
   2242   demux_asf_class_t *this;
   2243 
   2244   this = xine_xmalloc (sizeof (demux_asf_class_t));
   2245   this->config = xine->config;
   2246   this->xine = xine;
   2247 
   2248   this->demux_class.open_plugin = open_plugin;
   2249   this->demux_class.get_description = get_description;
   2250   this->demux_class.get_identifier = get_identifier;
   2251   this->demux_class.get_mimetypes = get_mimetypes;
   2252   this->demux_class.get_extensions = get_extensions;
   2253   this->demux_class.dispose = class_dispose;
   2254 
   2255   return this;
   2256 }
   2257 
   2258 
   2259 /*
   2260  * exported plugin catalog entry
   2261  */
   2262 
   2263 plugin_info_t xine_plugin_info[] = {
   2264   /* type, API, "name", version, special_info, init_function */
   2265   {PLUGIN_DEMUX, 20, "asf", XINE_VERSION_CODE, NULL, init_class}
   2266   ,
   2267   {PLUGIN_NONE, 0, "", 0, NULL, NULL}
   2268 };