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