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