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