demux_qt.c (96757B)
1 /* 2 * Copyright Copyright (C) 2001-2003 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 * Quicktime File Demuxer by Mike Melanson (melanson@pcisys.net) 21 * based on a Quicktime parsing experiment entitled 'lazyqt' 22 * 23 * Ideally, more documentation is forthcoming, but in the meantime: 24 * functional flow: 25 * create_qt_info 26 * open_qt_file 27 * parse_moov_atom 28 * parse_mvhd_atom 29 * parse_trak_atom 30 * build_frame_table 31 * free_qt_info 32 * 33 * $Id: demux_qt.c,v 1.1 2003/04/03 14:51:25 grothoff Exp $ 34 * 35 */ 36 37 #ifdef HAVE_CONFIG_H 38 #include "config.h" 39 #endif 40 41 #include <stdio.h> 42 #include <fcntl.h> 43 #include <unistd.h> 44 #include <string.h> 45 #include <stdlib.h> 46 #include <ctype.h> 47 #include <zlib.h> 48 49 #include "xine_internal.h" 50 #include "xineutils.h" 51 #include "demux.h" 52 #include "buffer.h" 53 #include "bswap.h" 54 55 #include "qtpalette.h" 56 57 typedef unsigned int qt_atom; 58 59 #define QT_ATOM( ch0, ch1, ch2, ch3 ) \ 60 ( (unsigned char)(ch3) | \ 61 ( (unsigned char)(ch2) << 8 ) | \ 62 ( (unsigned char)(ch1) << 16 ) | \ 63 ( (unsigned char)(ch0) << 24 ) ) 64 65 /* top level atoms */ 66 #define FREE_ATOM QT_ATOM('f', 'r', 'e', 'e') 67 #define JUNK_ATOM QT_ATOM('j', 'u', 'n', 'k') 68 #define MDAT_ATOM QT_ATOM('m', 'd', 'a', 't') 69 #define MOOV_ATOM QT_ATOM('m', 'o', 'o', 'v') 70 #define PNOT_ATOM QT_ATOM('p', 'n', 'o', 't') 71 #define SKIP_ATOM QT_ATOM('s', 'k', 'i', 'p') 72 #define WIDE_ATOM QT_ATOM('w', 'i', 'd', 'e') 73 #define PICT_ATOM QT_ATOM('P', 'I', 'C', 'T') 74 #define FTYP_ATOM QT_ATOM('f', 't', 'y', 'p') 75 76 #define CMOV_ATOM QT_ATOM('c', 'm', 'o', 'v') 77 78 #define MVHD_ATOM QT_ATOM('m', 'v', 'h', 'd') 79 80 #define VMHD_ATOM QT_ATOM('v', 'm', 'h', 'd') 81 #define SMHD_ATOM QT_ATOM('s', 'm', 'h', 'd') 82 83 #define TRAK_ATOM QT_ATOM('t', 'r', 'a', 'k') 84 #define TKHD_ATOM QT_ATOM('t', 'k', 'h', 'd') 85 #define MDHD_ATOM QT_ATOM('m', 'd', 'h', 'd') 86 #define ELST_ATOM QT_ATOM('e', 'l', 's', 't') 87 88 /* atoms in a sample table */ 89 #define STSD_ATOM QT_ATOM('s', 't', 's', 'd') 90 #define STSZ_ATOM QT_ATOM('s', 't', 's', 'z') 91 #define STSC_ATOM QT_ATOM('s', 't', 's', 'c') 92 #define STCO_ATOM QT_ATOM('s', 't', 'c', 'o') 93 #define STTS_ATOM QT_ATOM('s', 't', 't', 's') 94 #define STSS_ATOM QT_ATOM('s', 't', 's', 's') 95 #define CO64_ATOM QT_ATOM('c', 'o', '6', '4') 96 97 #define ESDS_ATOM QT_ATOM('e', 's', 'd', 's') 98 #define WAVE_ATOM QT_ATOM('w', 'a', 'v', 'e') 99 100 #define IMA4_FOURCC QT_ATOM('i', 'm', 'a', '4') 101 #define MP4A_FOURCC QT_ATOM('m', 'p', '4', 'a') 102 #define TWOS_FOURCC QT_ATOM('t', 'w', 'o', 's') 103 #define SOWT_FOURCC QT_ATOM('s', 'o', 'w', 't') 104 105 #define UDTA_ATOM QT_ATOM('u', 'd', 't', 'a') 106 #define CPY_ATOM QT_ATOM(0xA9, 'c', 'p', 'y') 107 #define DES_ATOM QT_ATOM(0xA9, 'd', 'e', 's') 108 #define CMT_ATOM QT_ATOM(0xA9, 'c', 'm', 't') 109 110 #define RMDA_ATOM QT_ATOM('r', 'm', 'd', 'a') 111 #define RDRF_ATOM QT_ATOM('r', 'd', 'r', 'f') 112 #define RMDR_ATOM QT_ATOM('r', 'm', 'd', 'r') 113 #define RMVC_ATOM QT_ATOM('r', 'm', 'v', 'c') 114 #define QTIM_ATOM QT_ATOM('q', 't', 'i', 'm') 115 116 /* placeholder for cutting and pasting */ 117 #define _ATOM QT_ATOM('', '', '', '') 118 119 #define ATOM_PREAMBLE_SIZE 8 120 #define PALETTE_COUNT 256 121 122 #define MAX_PTS_DIFF 100000 123 124 /* network bandwidth, cribbed from src/input/input_mms.c */ 125 const int64_t bandwidths[] = { 14400, 19200, 28800, 33600, 34430, 57600, 126 115200, 262200, 393216, 524300, 1544000, 10485800 127 }; 128 129 /* these are things that can go wrong */ 130 typedef enum 131 { 132 QT_OK, 133 QT_FILE_READ_ERROR, 134 QT_NO_MEMORY, 135 QT_NOT_A_VALID_FILE, 136 QT_NO_MOOV_ATOM, 137 QT_NO_ZLIB, 138 QT_ZLIB_ERROR, 139 QT_HEADER_TROUBLE 140 } qt_error; 141 142 /* there are other types but these are the ones we usually care about */ 143 typedef enum 144 { 145 146 MEDIA_AUDIO, 147 MEDIA_VIDEO, 148 MEDIA_OTHER 149 } media_type; 150 151 typedef struct 152 { 153 int64_t offset; 154 unsigned int size; 155 int64_t pts; 156 int keyframe; 157 } qt_frame; 158 159 typedef struct 160 { 161 unsigned int track_duration; 162 unsigned int media_time; 163 } edit_list_table_t; 164 165 typedef struct 166 { 167 unsigned int first_chunk; 168 unsigned int samples_per_chunk; 169 } sample_to_chunk_table_t; 170 171 typedef struct 172 { 173 unsigned int count; 174 unsigned int duration; 175 } time_to_sample_table_t; 176 177 typedef struct 178 { 179 unsigned char *url; 180 int64_t data_rate; 181 int qtim_version; 182 } reference_t; 183 184 typedef struct 185 { 186 187 /* trak description */ 188 media_type type; 189 union 190 { 191 192 struct 193 { 194 unsigned int codec_fourcc; 195 unsigned int codec_buftype; 196 unsigned int width; 197 unsigned int height; 198 int palette_count; 199 palette_entry_t palette[PALETTE_COUNT]; 200 int depth; 201 int edit_list_compensation; /* special trick for edit lists */ 202 } video; 203 204 struct 205 { 206 unsigned int codec_fourcc; 207 unsigned int codec_buftype; 208 unsigned int sample_rate; 209 unsigned int channels; 210 unsigned int bits; 211 unsigned int vbr; 212 unsigned int wave_present; 213 xine_waveformatex wave; 214 215 /* special audio parameters */ 216 unsigned int samples_per_packet; 217 unsigned int bytes_per_packet; 218 unsigned int bytes_per_frame; 219 unsigned int bytes_per_sample; 220 unsigned int samples_per_frame; 221 } audio; 222 223 } properties; 224 225 /* internal frame table corresponding to this trak */ 226 qt_frame *frames; 227 unsigned int frame_count; 228 unsigned int current_frame; 229 230 /* trak timescale */ 231 unsigned int timescale; 232 233 /* flags that indicate how a trak is supposed to be used */ 234 unsigned int flags; 235 236 /* decoder data pass information to the AAC decoder */ 237 void *decoder_config; 238 int decoder_config_len; 239 240 /* verbatim copy of the stsd atom */ 241 int stsd_size; 242 void *stsd; 243 244 /****************************************/ 245 /* temporary tables for loading a chunk */ 246 247 /* edit list table */ 248 unsigned int edit_list_count; 249 edit_list_table_t *edit_list_table; 250 251 /* chunk offsets */ 252 unsigned int chunk_offset_count; 253 int64_t *chunk_offset_table; 254 255 /* sample sizes */ 256 unsigned int sample_size; 257 unsigned int sample_size_count; 258 unsigned int *sample_size_table; 259 260 /* sync samples, a.k.a., keyframes */ 261 unsigned int sync_sample_count; 262 unsigned int *sync_sample_table; 263 264 /* sample to chunk table */ 265 unsigned int sample_to_chunk_count; 266 sample_to_chunk_table_t *sample_to_chunk_table; 267 268 /* time to sample table */ 269 unsigned int time_to_sample_count; 270 time_to_sample_table_t *time_to_sample_table; 271 272 } qt_trak; 273 274 typedef struct 275 { 276 int compressed_header; /* 1 if there was a compressed moov; just FYI */ 277 278 unsigned int creation_time; /* in ms since Jan-01-1904 */ 279 unsigned int modification_time; 280 unsigned int timescale; /* base clock frequency is Hz */ 281 unsigned int duration; 282 283 int64_t moov_first_offset; 284 285 int trak_count; 286 qt_trak *traks; 287 288 /* the trak numbers that won their respective frame count competitions */ 289 int video_trak; 290 int audio_trak; 291 int seek_flag; /* this is set to indicate that a seek has just occurred */ 292 293 char *copyright; 294 char *description; 295 char *comment; 296 297 /* a QT movie may contain a number of references pointing to URLs */ 298 reference_t *references; 299 int reference_count; 300 int chosen_reference; 301 302 /* need to know base MRL to construct URLs from relative paths */ 303 char *base_mrl; 304 305 qt_error last_error; 306 } qt_info; 307 308 typedef struct 309 { 310 311 demux_plugin_t demux_plugin; 312 313 xine_stream_t *stream; 314 315 config_values_t *config; 316 317 fifo_buffer_t *video_fifo; 318 fifo_buffer_t *audio_fifo; 319 320 input_plugin_t *input; 321 322 int status; 323 324 qt_info *qt; 325 xine_bmiheader bih; 326 unsigned int current_frame; 327 unsigned int last_frame; 328 329 off_t data_start; 330 off_t data_size; 331 332 int64_t bandwidth; 333 334 char last_mrl[1024]; 335 } demux_qt_t; 336 337 typedef struct 338 { 339 340 demux_class_t demux_class; 341 342 /* class-wide, global variables here */ 343 344 xine_t *xine; 345 config_values_t *config; 346 } demux_qt_class_t; 347 348 /********************************************************************** 349 * lazyqt special debugging functions 350 **********************************************************************/ 351 352 /* define DEBUG_ATOM_LOAD as 1 to get a verbose parsing of the relevant 353 * atoms */ 354 #define DEBUG_ATOM_LOAD 0 355 356 /* define DEBUG_EDIT_LIST as 1 to get a detailed look at how the demuxer is 357 * handling edit lists */ 358 #define DEBUG_EDIT_LIST 0 359 360 /* define DEBUG_FRAME_TABLE as 1 to dump the complete frame table that the 361 * demuxer plans to use during file playback */ 362 #define DEBUG_FRAME_TABLE 0 363 364 /* define DEBUG_VIDEO_DEMUX as 1 to see details about the video chunks the 365 * demuxer is sending off to the video decoder */ 366 #define DEBUG_VIDEO_DEMUX 0 367 368 /* define DEBUG_AUDIO_DEMUX as 1 to see details about the audio chunks the 369 * demuxer is sending off to the audio decoder */ 370 #define DEBUG_AUDIO_DEMUX 0 371 372 /* Define DEBUG_DUMP_MOOV as 1 to dump the raw moov atom to disk. This is 373 * particularly useful in debugging a file with a compressed moov (cmov) 374 * atom. The atom will be dumped to the filename specified as 375 * RAW_MOOV_FILENAME. */ 376 #define DEBUG_DUMP_MOOV 0 377 #define RAW_MOOV_FILENAME "moovatom.raw" 378 379 #if DEBUG_ATOM_LOAD 380 #define debug_atom_load printf 381 #else 382 static inline void 383 debug_atom_load (const char *format, ...) 384 { 385 } 386 #endif 387 388 #if DEBUG_EDIT_LIST 389 #define debug_edit_list printf 390 #else 391 static inline void 392 debug_edit_list (const char *format, ...) 393 { 394 } 395 #endif 396 397 #if DEBUG_FRAME_TABLE 398 #define debug_frame_table printf 399 #else 400 static inline void 401 debug_frame_table (const char *format, ...) 402 { 403 } 404 #endif 405 406 #if DEBUG_VIDEO_DEMUX 407 #define debug_video_demux printf 408 #else 409 static inline void 410 debug_video_demux (const char *format, ...) 411 { 412 } 413 #endif 414 415 #if DEBUG_AUDIO_DEMUX 416 #define debug_audio_demux printf 417 #else 418 static inline void 419 debug_audio_demux (const char *format, ...) 420 { 421 } 422 #endif 423 424 static void 425 hexdump (char *buf, int length) 426 { 427 428 int i; 429 430 printf ("demux_qt: ascii contents>"); 431 for (i = 0; i < length; i++) 432 { 433 unsigned char c = buf[i]; 434 435 if ((c >= 32) && (c < 128)) 436 printf ("%c", c); 437 else 438 printf ("."); 439 } 440 printf ("\n"); 441 442 printf 443 ("demux_qt: complete hexdump of package follows:\ndemux_qt 0x0000: "); 444 for (i = 0; i < length; i++) 445 { 446 unsigned char c = buf[i]; 447 448 printf ("%02x", c); 449 450 if ((i % 16) == 15) 451 printf ("\ndemux_qt 0x%04x: ", i); 452 453 if ((i % 2) == 1) 454 printf (" "); 455 456 } 457 printf ("\n"); 458 } 459 460 static inline void 461 dump_moov_atom (unsigned char *moov_atom, int moov_atom_size) 462 { 463 #if DEBUG_DUMP_MOOV 464 465 FILE *f; 466 467 f = fopen (RAW_MOOV_FILENAME, "w"); 468 if (!f) 469 { 470 perror (RAW_MOOV_FILENAME); 471 return; 472 } 473 474 if (fwrite (moov_atom, moov_atom_size, 1, f) != 1) 475 printf (" qt debug: could not write moov atom to disk\n"); 476 477 fclose (f); 478 479 #endif 480 } 481 482 /********************************************************************** 483 * lazyqt functions 484 **********************************************************************/ 485 486 /* 487 * This function traverses a file and looks for a moov atom. Returns the 488 * file offset of the beginning of the moov atom (that means the offset 489 * of the 4-byte length preceding the characters 'moov'). Returns -1 490 * if no moov atom was found. 491 * 492 * Note: Do not count on the input stream being positioned anywhere in 493 * particular when this function is finished. 494 */ 495 static void 496 find_moov_atom (input_plugin_t * input, off_t * moov_offset, 497 int64_t * moov_size) 498 { 499 500 off_t atom_size; 501 qt_atom atom; 502 unsigned char atom_preamble[ATOM_PREAMBLE_SIZE]; 503 504 /* init the passed variables */ 505 *moov_offset = *moov_size = -1; 506 507 /* take it from the top */ 508 if (input->seek (input, 0, SEEK_SET) != 0) 509 return; 510 511 /* traverse through the input */ 512 while (*moov_offset == -1) 513 { 514 if (input->read (input, atom_preamble, ATOM_PREAMBLE_SIZE) != 515 ATOM_PREAMBLE_SIZE) 516 break; 517 518 atom_size = BE_32 (&atom_preamble[0]); 519 atom = BE_32 (&atom_preamble[4]); 520 521 /* if the moov atom is found, log the position and break from the loop */ 522 if (atom == MOOV_ATOM) 523 { 524 *moov_offset = input->get_current_pos (input) - ATOM_PREAMBLE_SIZE; 525 *moov_size = atom_size; 526 break; 527 } 528 529 /* special case alert: 'free' atoms are known to contain 'cmov' atoms. 530 * If this is a free atom, check for cmov immediately following. 531 * QT Player can handle it, so xine should too. */ 532 if (atom == FREE_ATOM) 533 { 534 535 /* get the next atom preamble */ 536 if (input->read (input, atom_preamble, ATOM_PREAMBLE_SIZE) != 537 ATOM_PREAMBLE_SIZE) 538 break; 539 540 /* if there is a cmov, qualify this free atom as the moov atom */ 541 if (BE_32 (&atom_preamble[4]) == CMOV_ATOM) 542 { 543 /* pos = current pos minus 2 atom preambles */ 544 *moov_offset = 545 input->get_current_pos (input) - ATOM_PREAMBLE_SIZE * 2; 546 *moov_size = atom_size; 547 break; 548 } 549 else 550 { 551 /* otherwise, rewind the stream */ 552 input->seek (input, -ATOM_PREAMBLE_SIZE, SEEK_CUR); 553 } 554 } 555 556 /* if this atom is not the moov atom, make sure that it is at least one 557 * of the other top-level QT atom */ 558 if ((atom != FREE_ATOM) && 559 (atom != JUNK_ATOM) && 560 (atom != MDAT_ATOM) && 561 (atom != PNOT_ATOM) && 562 (atom != SKIP_ATOM) && 563 (atom != WIDE_ATOM) && (atom != PICT_ATOM) && (atom != FTYP_ATOM)) 564 break; 565 566 /* 64-bit length special case */ 567 if (atom_size == 1) 568 { 569 if (input->read (input, atom_preamble, ATOM_PREAMBLE_SIZE) != 570 ATOM_PREAMBLE_SIZE) 571 break; 572 573 atom_size = BE_32 (&atom_preamble[0]); 574 atom_size <<= 32; 575 atom_size |= BE_32 (&atom_preamble[4]); 576 atom_size -= ATOM_PREAMBLE_SIZE * 2; 577 } 578 else 579 atom_size -= ATOM_PREAMBLE_SIZE; 580 581 input->seek (input, atom_size, SEEK_CUR); 582 } 583 584 /* reset to the start of the stream on the way out */ 585 input->seek (input, 0, SEEK_SET); 586 } 587 588 /* create a qt_info structure or return NULL if no memory */ 589 qt_info * 590 create_qt_info (void) 591 { 592 qt_info *info; 593 594 info = (qt_info *) malloc (sizeof (qt_info)); 595 596 if (!info) 597 return NULL; 598 599 info->compressed_header = 0; 600 601 info->creation_time = 0; 602 info->modification_time = 0; 603 info->timescale = 0; 604 info->duration = 0; 605 606 info->trak_count = 0; 607 info->traks = NULL; 608 609 info->video_trak = -1; 610 info->audio_trak = -1; 611 612 info->copyright = NULL; 613 info->description = NULL; 614 info->comment = NULL; 615 616 info->references = NULL; 617 info->reference_count = 0; 618 info->chosen_reference = -1; 619 620 info->base_mrl = NULL; 621 622 info->last_error = QT_OK; 623 624 return info; 625 } 626 627 /* release a qt_info structure and associated data */ 628 void 629 free_qt_info (qt_info * info) 630 { 631 632 int i; 633 634 if (info) 635 { 636 if (info->traks) 637 { 638 for (i = 0; i < info->trak_count; i++) 639 { 640 free (info->traks[i].frames); 641 free (info->traks[i].edit_list_table); 642 free (info->traks[i].chunk_offset_table); 643 /* this pointer might have been set to -1 as a special case */ 644 if (info->traks[i].sample_size_table != (void *) -1) 645 free (info->traks[i].sample_size_table); 646 free (info->traks[i].sync_sample_table); 647 free (info->traks[i].sample_to_chunk_table); 648 free (info->traks[i].time_to_sample_table); 649 free (info->traks[i].decoder_config); 650 free (info->traks[i].stsd); 651 } 652 free (info->traks); 653 } 654 if (info->references) 655 { 656 for (i = 0; i < info->reference_count; i++) 657 free (info->references[i].url); 658 free (info->references); 659 } 660 free (info->base_mrl); 661 free (info->copyright); 662 free (info->description); 663 free (info->comment); 664 free (info); 665 info = NULL; 666 } 667 } 668 669 /* returns 1 if the file is determined to be a QT file, 0 otherwise */ 670 static int 671 is_qt_file (input_plugin_t * qt_file) 672 { 673 674 off_t moov_atom_offset = -1; 675 int64_t moov_atom_size = -1; 676 int i; 677 unsigned char atom_preamble[ATOM_PREAMBLE_SIZE]; 678 unsigned char preview[MAX_PREVIEW_SIZE]; 679 int len; 680 681 /* if the input is non-seekable, be much more stringent about qualifying 682 * a QT file: In this case, the moov must be the first atom in the file */ 683 if ((qt_file->get_capabilities (qt_file) & INPUT_CAP_SEEKABLE) == 0) 684 { 685 len = 686 qt_file->get_optional_data (qt_file, preview, 687 INPUT_OPTIONAL_DATA_PREVIEW); 688 if (BE_32 (&preview[4]) == MOOV_ATOM) 689 return 1; 690 else 691 return 0; 692 } 693 694 find_moov_atom (qt_file, &moov_atom_offset, &moov_atom_size); 695 if (moov_atom_offset == -1) 696 { 697 return 0; 698 } 699 else 700 { 701 /* check that the next atom in the chunk contains alphanumeric 702 * characters in the atom type field; if not, disqualify the file 703 * as a QT file */ 704 qt_file->seek (qt_file, moov_atom_offset + ATOM_PREAMBLE_SIZE, 705 SEEK_SET); 706 if (qt_file->read (qt_file, atom_preamble, ATOM_PREAMBLE_SIZE) != 707 ATOM_PREAMBLE_SIZE) 708 return 0; 709 710 for (i = 4; i < 8; i++) 711 if (!isalnum (atom_preamble[i])) 712 return 0; 713 return 1; 714 } 715 } 716 717 /* fetch interesting information from the movie header atom */ 718 static void 719 parse_mvhd_atom (qt_info * info, unsigned char *mvhd_atom) 720 { 721 722 info->creation_time = BE_32 (&mvhd_atom[0x0C]); 723 info->modification_time = BE_32 (&mvhd_atom[0x10]); 724 info->timescale = BE_32 (&mvhd_atom[0x14]); 725 info->duration = BE_32 (&mvhd_atom[0x18]); 726 727 } 728 729 /* helper function from mplayer's parse_mp4.c */ 730 static int 731 mp4_read_descr_len (unsigned char *s, uint32_t * length) 732 { 733 uint8_t b; 734 uint8_t numBytes = 0; 735 736 *length = 0; 737 738 do 739 { 740 b = *s++; 741 numBytes++; 742 *length = (*length << 7) | (b & 0x7F); 743 } 744 while ((b & 0x80) && numBytes < 4); 745 746 return numBytes; 747 } 748 749 /* 750 * This function traverses through a trak atom searching for the sample 751 * table atoms, which it loads into an internal trak structure. 752 */ 753 static qt_error 754 parse_trak_atom (qt_trak * trak, unsigned char *trak_atom) 755 { 756 757 int i, j; 758 unsigned int trak_atom_size = BE_32 (&trak_atom[0]); 759 qt_atom current_atom; 760 unsigned int current_atom_size; 761 qt_error last_error = QT_OK; 762 763 /* for palette traversal */ 764 int color_depth; 765 int color_flag; 766 int color_start; 767 int color_count; 768 int color_end; 769 int color_index; 770 int color_dec; 771 int color_greyscale; 772 unsigned char *color_table; 773 774 /* initialize trak structure */ 775 trak->edit_list_count = 0; 776 trak->edit_list_table = NULL; 777 trak->chunk_offset_count = 0; 778 trak->chunk_offset_table = NULL; 779 trak->sample_size = 0; 780 trak->sample_size_count = 0; 781 trak->sample_size_table = NULL; 782 trak->sync_sample_table = 0; 783 trak->sync_sample_table = NULL; 784 trak->sample_to_chunk_count = 0; 785 trak->sample_to_chunk_table = NULL; 786 trak->time_to_sample_count = 0; 787 trak->time_to_sample_table = NULL; 788 trak->frames = NULL; 789 trak->frame_count = 0; 790 trak->current_frame = 0; 791 trak->timescale = 0; 792 trak->flags = 0; 793 trak->decoder_config = NULL; 794 trak->decoder_config_len = 0; 795 trak->stsd = NULL; 796 trak->stsd_size = 0; 797 memset (&trak->properties, 0, sizeof (trak->properties)); 798 799 /* default type */ 800 trak->type = MEDIA_OTHER; 801 802 /* search for media type atoms */ 803 for (i = ATOM_PREAMBLE_SIZE; i < trak_atom_size - 4; i++) 804 { 805 current_atom = BE_32 (&trak_atom[i]); 806 807 if (current_atom == VMHD_ATOM) 808 { 809 trak->type = MEDIA_VIDEO; 810 break; 811 } 812 else if (current_atom == SMHD_ATOM) 813 { 814 trak->type = MEDIA_AUDIO; 815 break; 816 } 817 } 818 819 debug_atom_load (" qt: parsing %s trak atom\n", 820 (trak->type == MEDIA_VIDEO) ? "video" : 821 (trak->type == MEDIA_AUDIO) ? "audio" : "other"); 822 823 /* search for the useful atoms */ 824 for (i = ATOM_PREAMBLE_SIZE; i < trak_atom_size - 4; i++) 825 { 826 current_atom_size = BE_32 (&trak_atom[i - 4]); 827 current_atom = BE_32 (&trak_atom[i]); 828 829 if (current_atom == TKHD_ATOM) 830 { 831 trak->flags = BE_16 (&trak_atom[i + 6]); 832 833 if (trak->type == MEDIA_VIDEO) 834 { 835 /* fetch display parameters */ 836 if (!trak->properties.video.width || 837 !trak->properties.video.height) 838 { 839 840 trak->properties.video.width = BE_16 (&trak_atom[i + 0x50]); 841 trak->properties.video.height = 842 BE_16 (&trak_atom[i + 0x54]); 843 } 844 } 845 } 846 else if (current_atom == ELST_ATOM) 847 { 848 849 /* there should only be one edit list table */ 850 if (trak->edit_list_table) 851 { 852 last_error = QT_HEADER_TROUBLE; 853 goto free_trak; 854 } 855 856 trak->edit_list_count = BE_32 (&trak_atom[i + 8]); 857 858 debug_atom_load (" qt elst atom (edit list atom): %d entries\n", 859 trak->edit_list_count); 860 861 trak->edit_list_table = 862 (edit_list_table_t *) malloc (trak->edit_list_count * 863 sizeof (edit_list_table_t)); 864 if (!trak->edit_list_table) 865 { 866 last_error = QT_NO_MEMORY; 867 goto free_trak; 868 } 869 870 /* load the edit list table */ 871 for (j = 0; j < trak->edit_list_count; j++) 872 { 873 trak->edit_list_table[j].track_duration = 874 BE_32 (&trak_atom[i + 12 + j * 12 + 0]); 875 trak->edit_list_table[j].media_time = 876 BE_32 (&trak_atom[i + 12 + j * 12 + 4]); 877 debug_atom_load 878 (" %d: track duration = %d, media time = %d\n", j, 879 trak->edit_list_table[j].track_duration, 880 trak->edit_list_table[j].media_time); 881 } 882 883 } 884 else if (current_atom == MDHD_ATOM) 885 trak->timescale = BE_32 (&trak_atom[i + 0x10]); 886 else if (current_atom == STSD_ATOM) 887 { 888 889 int hack_adjust; 890 891 debug_atom_load ("demux_qt: stsd atom\n"); 892 #if DEBUG_ATOM_LOAD 893 hexdump (&trak_atom[i], current_atom_size); 894 #endif 895 896 /* copy whole stsd atom so it can later be sent to the decoder */ 897 898 trak->stsd_size = current_atom_size; 899 trak->stsd = realloc (trak->stsd, current_atom_size); 900 memset (trak->stsd, 0, trak->stsd_size); 901 902 /* awful, awful hack to support a certain type of stsd atom that 903 * contains more than 1 video description atom */ 904 if (BE_32 (&trak_atom[i + 8]) == 1) 905 { 906 /* normal case */ 907 memcpy (trak->stsd, &trak_atom[i], current_atom_size); 908 hack_adjust = 0; 909 } 910 else 911 { 912 /* pathological case; take this route until a more definite 913 * solution is found: jump over the first atom video 914 * description atom */ 915 916 /* copy the first 12 bytes since those remain the same */ 917 memcpy (trak->stsd, &trak_atom[i], 12); 918 919 /* skip to the second atom and copy it */ 920 hack_adjust = BE_32 (&trak_atom[i + 0x0C]); 921 memcpy (trak->stsd + 12, &trak_atom[i + 0x0C + hack_adjust], 922 BE_32 (&trak_atom[i + 0x0C + hack_adjust])); 923 924 /* use this variable to reference into the second atom, and 925 * fix at the end of the stsd parser */ 926 i += hack_adjust; 927 } 928 929 if (trak->type == MEDIA_VIDEO) 930 { 931 932 /* initialize to sane values */ 933 trak->properties.video.width = 0; 934 trak->properties.video.height = 0; 935 trak->properties.video.depth = 0; 936 937 /* assume no palette at first */ 938 trak->properties.video.palette_count = 0; 939 940 /* fetch video parameters */ 941 if (BE_16 (&trak_atom[i + 0x2C]) && 942 BE_16 (&trak_atom[i + 0x2E])) 943 { 944 trak->properties.video.width = BE_16 (&trak_atom[i + 0x2C]); 945 trak->properties.video.height = 946 BE_16 (&trak_atom[i + 0x2E]); 947 } 948 trak->properties.video.codec_fourcc = 949 ME_32 (&trak_atom[i + 0x10]); 950 951 /* figure out the palette situation */ 952 color_depth = trak_atom[i + 0x5F]; 953 trak->properties.video.depth = color_depth; 954 color_greyscale = color_depth & 0x20; 955 color_depth &= 0x1F; 956 957 /* if the depth is 2, 4, or 8 bpp, file is palettized */ 958 if ((color_depth == 2) || (color_depth == 4) 959 || (color_depth == 8)) 960 { 961 962 color_flag = BE_16 (&trak_atom[i + 0x60]); 963 964 if (color_greyscale) 965 { 966 967 trak->properties.video.palette_count = 1 << color_depth; 968 969 /* compute the greyscale palette */ 970 color_index = 255; 971 color_dec = 256 / 972 (trak->properties.video.palette_count - 1); 973 for (j = 0; 974 j < trak->properties.video.palette_count; j++) 975 { 976 977 trak->properties.video.palette[j].r = color_index; 978 trak->properties.video.palette[j].g = color_index; 979 trak->properties.video.palette[j].b = color_index; 980 color_index -= color_dec; 981 if (color_index < 0) 982 color_index = 0; 983 } 984 985 } 986 else if (color_flag & 0x08) 987 { 988 989 /* if flag bit 3 is set, load the default palette */ 990 trak->properties.video.palette_count = 1 << color_depth; 991 992 if (color_depth == 2) 993 color_table = qt_default_palette_4; 994 else if (color_depth == 4) 995 color_table = qt_default_palette_16; 996 else 997 color_table = qt_default_palette_256; 998 999 for (j = 0; 1000 j < trak->properties.video.palette_count; j++) 1001 { 1002 1003 trak->properties.video.palette[j].r = 1004 color_table[j * 4 + 0]; 1005 trak->properties.video.palette[j].g = 1006 color_table[j * 4 + 1]; 1007 trak->properties.video.palette[j].b = 1008 color_table[j * 4 + 2]; 1009 1010 } 1011 1012 } 1013 else 1014 { 1015 1016 /* load the palette from the file */ 1017 color_start = BE_32 (&trak_atom[i + 0x62]); 1018 color_count = BE_16 (&trak_atom[i + 0x66]); 1019 color_end = BE_16 (&trak_atom[i + 0x68]); 1020 trak->properties.video.palette_count = color_end + 1; 1021 1022 for (j = color_start; j <= color_end; j++) 1023 { 1024 1025 color_index = BE_16 (&trak_atom[i + 0x6A + j * 8]); 1026 if (color_count & 0x8000) 1027 color_index = j; 1028 if (color_index < 1029 trak->properties.video.palette_count) 1030 { 1031 trak->properties.video.palette[color_index].r = 1032 trak_atom[i + 0x6A + j * 8 + 2]; 1033 trak->properties.video.palette[color_index].g = 1034 trak_atom[i + 0x6A + j * 8 + 4]; 1035 trak->properties.video.palette[color_index].b = 1036 trak_atom[i + 0x6A + j * 8 + 6]; 1037 } 1038 } 1039 } 1040 } 1041 else 1042 trak->properties.video.palette_count = 0; 1043 1044 debug_atom_load (" video description\n"); 1045 debug_atom_load 1046 (" %dx%d, video fourcc = '%c%c%c%c' (%02X%02X%02X%02X)\n", 1047 trak->properties.video.width, trak->properties.video.height, 1048 trak_atom[i + 0x10], trak_atom[i + 0x11], 1049 trak_atom[i + 0x12], trak_atom[i + 0x13], 1050 trak_atom[i + 0x10], trak_atom[i + 0x11], 1051 trak_atom[i + 0x12], trak_atom[i + 0x13]); 1052 debug_atom_load (" %d RGB colors\n", 1053 trak->properties.video.palette_count); 1054 for (j = 0; j < trak->properties.video.palette_count; j++) 1055 debug_atom_load (" %d: %3d %3d %3d\n", 1056 j, 1057 trak->properties.video.palette[j].r, 1058 trak->properties.video.palette[j].g, 1059 trak->properties.video.palette[j].b); 1060 1061 } 1062 else if (trak->type == MEDIA_AUDIO) 1063 { 1064 1065 /* fetch audio parameters */ 1066 trak->properties.audio.codec_fourcc = 1067 ME_32 (&trak_atom[i + 0x10]); 1068 trak->properties.audio.sample_rate = 1069 BE_16 (&trak_atom[i + 0x2C]); 1070 trak->properties.audio.channels = trak_atom[i + 0x25]; 1071 trak->properties.audio.bits = trak_atom[i + 0x27]; 1072 1073 /* assume uncompressed audio parameters */ 1074 trak->properties.audio.bytes_per_sample = 1075 trak->properties.audio.bits / 8; 1076 trak->properties.audio.samples_per_frame = 1077 trak->properties.audio.channels; 1078 trak->properties.audio.bytes_per_frame = 1079 trak->properties.audio.bytes_per_sample * 1080 trak->properties.audio.samples_per_frame; 1081 trak->properties.audio.samples_per_packet = 1082 trak->properties.audio.samples_per_frame; 1083 trak->properties.audio.bytes_per_packet = 1084 trak->properties.audio.bytes_per_sample; 1085 1086 /* special case time: some ima4-encoded files don't have the 1087 * extra header; compensate */ 1088 if (BE_32 (&trak_atom[i + 0x10]) == IMA4_FOURCC) 1089 { 1090 trak->properties.audio.samples_per_packet = 64; 1091 trak->properties.audio.bytes_per_packet = 34; 1092 trak->properties.audio.bytes_per_frame = 34 * 1093 trak->properties.audio.channels; 1094 trak->properties.audio.bytes_per_sample = 2; 1095 trak->properties.audio.samples_per_frame = 64 * 1096 trak->properties.audio.channels; 1097 } 1098 1099 /* it's time to dig a little deeper to determine the real audio 1100 * properties; if a the stsd compressor atom has 0x24 bytes, it 1101 * appears to be a handler for uncompressed data; if there are an 1102 * extra 0x10 bytes, there are some more useful decoding params */ 1103 if (BE_32 (&trak_atom[i + 0x0C]) > 0x24) 1104 { 1105 1106 if (BE_32 (&trak_atom[i + 0x30])) 1107 trak->properties.audio.samples_per_packet = 1108 BE_32 (&trak_atom[i + 0x30]); 1109 if (BE_32 (&trak_atom[i + 0x34])) 1110 trak->properties.audio.bytes_per_packet = 1111 BE_32 (&trak_atom[i + 0x34]); 1112 if (BE_32 (&trak_atom[i + 0x38])) 1113 trak->properties.audio.bytes_per_frame = 1114 BE_32 (&trak_atom[i + 0x38]); 1115 if (BE_32 (&trak_atom[i + 0x3C])) 1116 trak->properties.audio.bytes_per_sample = 1117 BE_32 (&trak_atom[i + 0x3C]); 1118 trak->properties.audio.samples_per_frame = 1119 (trak->properties.audio.bytes_per_frame / 1120 trak->properties.audio.bytes_per_packet) * 1121 trak->properties.audio.samples_per_packet; 1122 1123 } 1124 1125 /* see if the trak deserves a promotion to VBR */ 1126 if (BE_16 (&trak_atom[i + 0x28]) == 0xFFFE) 1127 trak->properties.audio.vbr = 1; 1128 else 1129 trak->properties.audio.vbr = 0; 1130 1131 /* if this is MP4 audio, mark the trak as VBR */ 1132 if (BE_32 (&trak_atom[i + 0x10]) == MP4A_FOURCC) 1133 trak->properties.audio.vbr = 1; 1134 1135 /* check for a MS-style WAVE format header */ 1136 if ((current_atom_size >= 0x48) && 1137 (BE_32 (&trak_atom[i + 0x44]) == WAVE_ATOM)) 1138 { 1139 trak->properties.audio.wave_present = 1; 1140 memcpy (&trak->properties.audio.wave, 1141 &trak_atom[i + 0x5C], 1142 sizeof (trak->properties.audio.wave)); 1143 xine_waveformatex_le2me (&trak->properties.audio.wave); 1144 } 1145 else 1146 { 1147 trak->properties.audio.wave_present = 0; 1148 } 1149 1150 debug_atom_load (" audio description\n"); 1151 debug_atom_load 1152 (" %d Hz, %d bits, %d channels, %saudio fourcc = '%c%c%c%c' (%02X%02X%02X%02X)\n", 1153 trak->properties.audio.sample_rate, 1154 trak->properties.audio.bits, trak->properties.audio.channels, 1155 (trak->properties.audio.vbr) ? "vbr, " : "", 1156 trak_atom[i + 0x10], trak_atom[i + 0x11], 1157 trak_atom[i + 0x12], trak_atom[i + 0x13], 1158 trak_atom[i + 0x10], trak_atom[i + 0x11], 1159 trak_atom[i + 0x12], trak_atom[i + 0x13]); 1160 if (BE_32 (&trak_atom[i + 0x0C]) > 0x24) 1161 { 1162 debug_atom_load 1163 (" %d samples/packet, %d bytes/packet, %d bytes/frame\n", 1164 trak->properties.audio.samples_per_packet, 1165 trak->properties.audio.bytes_per_packet, 1166 trak->properties.audio.bytes_per_frame); 1167 debug_atom_load 1168 (" %d bytes/sample (%d samples/frame)\n", 1169 trak->properties.audio.bytes_per_sample, 1170 trak->properties.audio.samples_per_frame); 1171 } 1172 } 1173 1174 i -= hack_adjust; 1175 1176 } 1177 else if (current_atom == ESDS_ATOM) 1178 { 1179 1180 uint32_t len; 1181 1182 debug_atom_load (" qt/mpeg-4 esds atom\n"); 1183 1184 if ((trak->type == MEDIA_VIDEO) || (trak->type == MEDIA_AUDIO)) 1185 { 1186 1187 j = i + 8; 1188 if (trak_atom[j++] == 0x03) 1189 { 1190 j += mp4_read_descr_len (&trak_atom[j], &len); 1191 j++; 1192 } 1193 j += 2; 1194 if (trak_atom[j++] == 0x04) 1195 { 1196 j += mp4_read_descr_len (&trak_atom[j], &len); 1197 j += 13; 1198 if (trak_atom[j++] == 0x05) 1199 { 1200 j += mp4_read_descr_len (&trak_atom[j], &len); 1201 debug_atom_load 1202 (" decoder config is %d (0x%X) bytes long\n", 1203 len, len); 1204 trak->decoder_config = 1205 realloc (trak->decoder_config, len); 1206 trak->decoder_config_len = len; 1207 memcpy (trak->decoder_config, &trak_atom[j], len); 1208 } 1209 } 1210 } 1211 1212 } 1213 else if (current_atom == STSZ_ATOM) 1214 { 1215 1216 /* there should only be one of these atoms */ 1217 if (trak->sample_size_table) 1218 { 1219 last_error = QT_HEADER_TROUBLE; 1220 goto free_trak; 1221 } 1222 1223 trak->sample_size = BE_32 (&trak_atom[i + 8]); 1224 trak->sample_size_count = BE_32 (&trak_atom[i + 12]); 1225 1226 debug_atom_load 1227 (" qt stsz atom (sample size atom): sample size = %d, %d entries\n", 1228 trak->sample_size, trak->sample_size_count); 1229 1230 /* allocate space and load table only if sample size is 0 */ 1231 if (trak->sample_size == 0) 1232 { 1233 trak->sample_size_table = 1234 (unsigned int *) malloc (trak->sample_size_count * 1235 sizeof (unsigned int)); 1236 if (!trak->sample_size_table) 1237 { 1238 last_error = QT_NO_MEMORY; 1239 goto free_trak; 1240 } 1241 /* load the sample size table */ 1242 for (j = 0; j < trak->sample_size_count; j++) 1243 { 1244 trak->sample_size_table[j] = 1245 BE_32 (&trak_atom[i + 16 + j * 4]); 1246 debug_atom_load (" sample size %d: %d\n", 1247 j, trak->sample_size_table[j]); 1248 } 1249 } 1250 else 1251 /* set the pointer to non-NULL to indicate that the atom type has 1252 * already been seen for this trak atom */ 1253 trak->sample_size_table = (void *) -1; 1254 1255 } 1256 else if (current_atom == STSS_ATOM) 1257 { 1258 1259 /* there should only be one of these atoms */ 1260 if (trak->sync_sample_table) 1261 { 1262 last_error = QT_HEADER_TROUBLE; 1263 goto free_trak; 1264 } 1265 1266 trak->sync_sample_count = BE_32 (&trak_atom[i + 8]); 1267 1268 debug_atom_load 1269 (" qt stss atom (sample sync atom): %d sync samples\n", 1270 trak->sync_sample_count); 1271 1272 trak->sync_sample_table = 1273 (unsigned int *) malloc (trak->sync_sample_count * 1274 sizeof (unsigned int)); 1275 if (!trak->sync_sample_table) 1276 { 1277 last_error = QT_NO_MEMORY; 1278 goto free_trak; 1279 } 1280 1281 /* load the sync sample table */ 1282 for (j = 0; j < trak->sync_sample_count; j++) 1283 { 1284 trak->sync_sample_table[j] = BE_32 (&trak_atom[i + 12 + j * 4]); 1285 debug_atom_load 1286 (" sync sample %d: sample %d (%d) is a keyframe\n", j, 1287 trak->sync_sample_table[j], trak->sync_sample_table[j] - 1); 1288 } 1289 1290 } 1291 else if (current_atom == STCO_ATOM) 1292 { 1293 1294 /* there should only be one of either stco or co64 */ 1295 if (trak->chunk_offset_table) 1296 { 1297 last_error = QT_HEADER_TROUBLE; 1298 goto free_trak; 1299 } 1300 1301 trak->chunk_offset_count = BE_32 (&trak_atom[i + 8]); 1302 1303 debug_atom_load 1304 (" qt stco atom (32-bit chunk offset atom): %d chunk offsets\n", 1305 trak->chunk_offset_count); 1306 1307 trak->chunk_offset_table = 1308 (int64_t *) malloc (trak->chunk_offset_count * sizeof (int64_t)); 1309 if (!trak->chunk_offset_table) 1310 { 1311 last_error = QT_NO_MEMORY; 1312 goto free_trak; 1313 } 1314 1315 /* load the chunk offset table */ 1316 for (j = 0; j < trak->chunk_offset_count; j++) 1317 { 1318 trak->chunk_offset_table[j] = 1319 BE_32 (&trak_atom[i + 12 + j * 4]); 1320 debug_atom_load (" chunk %d @ 0x%llX\n", 1321 j, trak->chunk_offset_table[j]); 1322 } 1323 1324 } 1325 else if (current_atom == CO64_ATOM) 1326 { 1327 1328 /* there should only be one of either stco or co64 */ 1329 if (trak->chunk_offset_table) 1330 { 1331 last_error = QT_HEADER_TROUBLE; 1332 goto free_trak; 1333 } 1334 1335 trak->chunk_offset_count = BE_32 (&trak_atom[i + 8]); 1336 1337 debug_atom_load 1338 (" qt co64 atom (64-bit chunk offset atom): %d chunk offsets\n", 1339 trak->chunk_offset_count); 1340 1341 trak->chunk_offset_table = 1342 (int64_t *) malloc (trak->chunk_offset_count * sizeof (int64_t)); 1343 if (!trak->chunk_offset_table) 1344 { 1345 last_error = QT_NO_MEMORY; 1346 goto free_trak; 1347 } 1348 1349 /* load the 64-bit chunk offset table */ 1350 for (j = 0; j < trak->chunk_offset_count; j++) 1351 { 1352 trak->chunk_offset_table[j] = 1353 BE_32 (&trak_atom[i + 12 + j * 8 + 0]); 1354 trak->chunk_offset_table[j] <<= 32; 1355 trak->chunk_offset_table[j] |= 1356 BE_32 (&trak_atom[i + 12 + j * 8 + 4]); 1357 debug_atom_load (" chunk %d @ 0x%llX\n", 1358 j, trak->chunk_offset_table[j]); 1359 } 1360 1361 } 1362 else if (current_atom == STSC_ATOM) 1363 { 1364 1365 /* there should only be one of these atoms */ 1366 if (trak->sample_to_chunk_table) 1367 { 1368 last_error = QT_HEADER_TROUBLE; 1369 goto free_trak; 1370 } 1371 1372 trak->sample_to_chunk_count = BE_32 (&trak_atom[i + 8]); 1373 1374 debug_atom_load 1375 (" qt stsc atom (sample-to-chunk atom): %d entries\n", 1376 trak->sample_to_chunk_count); 1377 1378 trak->sample_to_chunk_table = 1379 (sample_to_chunk_table_t *) malloc (trak->sample_to_chunk_count * 1380 sizeof 1381 (sample_to_chunk_table_t)); 1382 if (!trak->sample_to_chunk_table) 1383 { 1384 last_error = QT_NO_MEMORY; 1385 goto free_trak; 1386 } 1387 1388 /* load the sample to chunk table */ 1389 for (j = 0; j < trak->sample_to_chunk_count; j++) 1390 { 1391 trak->sample_to_chunk_table[j].first_chunk = 1392 BE_32 (&trak_atom[i + 12 + j * 12 + 0]); 1393 trak->sample_to_chunk_table[j].samples_per_chunk = 1394 BE_32 (&trak_atom[i + 12 + j * 12 + 4]); 1395 debug_atom_load 1396 (" %d: %d samples/chunk starting at chunk %d (%d)\n", j, 1397 trak->sample_to_chunk_table[j].samples_per_chunk, 1398 trak->sample_to_chunk_table[j].first_chunk, 1399 trak->sample_to_chunk_table[j].first_chunk - 1); 1400 } 1401 1402 } 1403 else if (current_atom == STTS_ATOM) 1404 { 1405 1406 /* there should only be one of these atoms */ 1407 if (trak->time_to_sample_table) 1408 { 1409 last_error = QT_HEADER_TROUBLE; 1410 goto free_trak; 1411 } 1412 1413 trak->time_to_sample_count = BE_32 (&trak_atom[i + 8]); 1414 1415 debug_atom_load 1416 (" qt stts atom (time-to-sample atom): %d entries\n", 1417 trak->time_to_sample_count); 1418 1419 trak->time_to_sample_table = (time_to_sample_table_t *) malloc ((trak->time_to_sample_count + 1) * sizeof (time_to_sample_table_t)); 1420 if (!trak->time_to_sample_table) 1421 { 1422 last_error = QT_NO_MEMORY; 1423 goto free_trak; 1424 } 1425 1426 /* load the time to sample table */ 1427 for (j = 0; j < trak->time_to_sample_count; j++) 1428 { 1429 trak->time_to_sample_table[j].count = 1430 BE_32 (&trak_atom[i + 12 + j * 8 + 0]); 1431 trak->time_to_sample_table[j].duration = 1432 BE_32 (&trak_atom[i + 12 + j * 8 + 4]); 1433 debug_atom_load (" %d: count = %d, duration = %d\n", 1434 j, trak->time_to_sample_table[j].count, 1435 trak->time_to_sample_table[j].duration); 1436 } 1437 trak->time_to_sample_table[j].count = 0; /* terminate with zero */ 1438 } 1439 } 1440 1441 return QT_OK; 1442 1443 /* jump here to make sure everything is free'd and avoid leaking memory */ 1444 free_trak: 1445 free (trak->edit_list_table); 1446 free (trak->chunk_offset_table); 1447 /* this pointer might have been set to -1 as a special case */ 1448 if (trak->sample_size_table != (void *) -1) 1449 free (trak->sample_size_table); 1450 free (trak->sync_sample_table); 1451 free (trak->sample_to_chunk_table); 1452 free (trak->time_to_sample_table); 1453 free (trak->decoder_config); 1454 free (trak->stsd); 1455 1456 return last_error; 1457 } 1458 1459 /* Traverse through a reference atom and extract the URL and data rate. */ 1460 static qt_error 1461 parse_reference_atom (reference_t * ref, 1462 unsigned char *ref_atom, char *base_mrl) 1463 { 1464 1465 int i, j; 1466 unsigned int ref_atom_size = BE_32 (&ref_atom[0]); 1467 qt_atom current_atom; 1468 unsigned int current_atom_size; 1469 1470 /* initialize reference atom */ 1471 ref->url = NULL; 1472 ref->data_rate = 0; 1473 ref->qtim_version = 0; 1474 1475 /* traverse through the atom looking for the key atoms */ 1476 for (i = ATOM_PREAMBLE_SIZE; i < ref_atom_size - 4; i++) 1477 { 1478 1479 current_atom_size = BE_32 (&ref_atom[i - 4]); 1480 current_atom = BE_32 (&ref_atom[i]); 1481 1482 if (current_atom == RDRF_ATOM) 1483 { 1484 1485 /* if the URL starts with "http://", copy it */ 1486 if (strncmp (&ref_atom[i + 12], "http://", 7) == 0) 1487 { 1488 1489 /* URL is spec'd to terminate with a NULL; don't trust it */ 1490 ref->url = xine_xmalloc (BE_32 (&ref_atom[i + 12]) + 1); 1491 strncpy (ref->url, &ref_atom[i + 16], 1492 BE_32 (&ref_atom[i + 12])); 1493 ref->url[BE_32 (&ref_atom[i + 12]) - 1] = '\0'; 1494 1495 } 1496 else 1497 { 1498 1499 int string_size = 1500 strlen (base_mrl) + BE_32 (&ref_atom[i + 12]) + 1; 1501 1502 /* otherwise, append relative URL to base MRL */ 1503 ref->url = xine_xmalloc (string_size); 1504 strcpy (ref->url, base_mrl); 1505 strncat (ref->url, &ref_atom[i + 16], 1506 BE_32 (&ref_atom[i + 12])); 1507 ref->url[string_size - 1] = '\0'; 1508 } 1509 1510 debug_atom_load (" qt rdrf URL reference:\n %s\n", 1511 ref->url); 1512 1513 } 1514 else if (current_atom == RMDR_ATOM) 1515 { 1516 1517 /* load the data rate */ 1518 ref->data_rate = BE_32 (&ref_atom[i + 8]); 1519 ref->data_rate *= 10; 1520 1521 debug_atom_load (" qt rmdr data rate = %lld\n", ref->data_rate); 1522 1523 } 1524 else if (current_atom == RMVC_ATOM) 1525 { 1526 1527 debug_atom_load (" qt rmvc atom\n"); 1528 1529 /* search the rmvc atom for 'qtim'; 2 bytes will follow the qtim 1530 * chars so only search to 6 bytes to the end */ 1531 for (j = 4; j < current_atom_size - 6; j++) 1532 { 1533 1534 if (BE_32 (&ref_atom[i + j]) == QTIM_ATOM) 1535 { 1536 1537 ref->qtim_version = BE_16 (&ref_atom[i + j + 4]); 1538 debug_atom_load (" qtim version = %04X\n", 1539 ref->qtim_version); 1540 } 1541 } 1542 } 1543 } 1544 1545 return QT_OK; 1546 } 1547 1548 /* This is a little support function used to process the edit list when 1549 * building a frame table. */ 1550 #define MAX_DURATION 0x7FFFFFFFFFFFFFFF 1551 static void 1552 get_next_edit_list_entry (qt_trak * trak, 1553 int *edit_list_index, 1554 unsigned int *edit_list_media_time, 1555 int64_t * edit_list_duration, 1556 unsigned int global_timescale) 1557 { 1558 1559 /* if there is no edit list, set to max duration and get out */ 1560 if (!trak->edit_list_table) 1561 { 1562 1563 *edit_list_media_time = 0; 1564 *edit_list_duration = MAX_DURATION; 1565 debug_edit_list (" qt: no edit list table, initial = %d, %lld\n", 1566 *edit_list_media_time, *edit_list_duration); 1567 return; 1568 1569 } 1570 else 1571 while (*edit_list_index < trak->edit_list_count) 1572 { 1573 1574 /* otherwise, find an edit list entries whose media time != -1 */ 1575 if (trak->edit_list_table[*edit_list_index].media_time != -1) 1576 { 1577 1578 *edit_list_media_time = 1579 trak->edit_list_table[*edit_list_index].media_time; 1580 *edit_list_duration = 1581 trak->edit_list_table[*edit_list_index].track_duration; 1582 1583 /* duration is in global timescale units; convert to trak timescale */ 1584 *edit_list_duration *= trak->timescale; 1585 *edit_list_duration /= global_timescale; 1586 1587 *edit_list_index = *edit_list_index + 1; 1588 break; 1589 } 1590 1591 *edit_list_index = *edit_list_index + 1; 1592 } 1593 1594 /* on the way out, check if this is the last edit list entry; if so, 1595 * don't let the duration expire (so set it to an absurdly large value) 1596 */ 1597 if (*edit_list_index == trak->edit_list_count) 1598 *edit_list_duration = MAX_DURATION; 1599 debug_edit_list (" qt: edit list table exists, initial = %d, %lld\n", 1600 *edit_list_media_time, *edit_list_duration); 1601 } 1602 1603 static qt_error 1604 build_frame_table (qt_trak * trak, unsigned int global_timescale) 1605 { 1606 1607 int i, j; 1608 unsigned int frame_counter; 1609 unsigned int chunk_start, chunk_end; 1610 unsigned int samples_per_chunk; 1611 uint64_t current_offset; 1612 int64_t current_pts; 1613 unsigned int pts_index; 1614 unsigned int pts_index_countdown; 1615 unsigned int audio_frame_counter = 0; 1616 unsigned int edit_list_media_time; 1617 int64_t edit_list_duration; 1618 int64_t frame_duration = 0; 1619 unsigned int edit_list_index; 1620 unsigned int edit_list_pts_counter; 1621 1622 /* AUDIO and OTHER frame types follow the same rules; VIDEO and vbr audio 1623 * frame types follow a different set */ 1624 if ((trak->type == MEDIA_VIDEO) || (trak->properties.audio.vbr)) 1625 { 1626 1627 /* in this case, the total number of frames is equal to the number of 1628 * entries in the sample size table */ 1629 trak->frame_count = trak->sample_size_count; 1630 trak->frames = 1631 (qt_frame *) malloc (trak->frame_count * sizeof (qt_frame)); 1632 if (!trak->frames) 1633 return QT_NO_MEMORY; 1634 trak->current_frame = 0; 1635 1636 /* initialize more accounting variables */ 1637 frame_counter = 0; 1638 current_pts = 0; 1639 pts_index = 0; 1640 pts_index_countdown = trak->time_to_sample_table[pts_index].count; 1641 1642 /* iterate through each start chunk in the stsc table */ 1643 for (i = 0; i < trak->sample_to_chunk_count; i++) 1644 { 1645 /* iterate from the first chunk of the current table entry to 1646 * the first chunk of the next table entry */ 1647 chunk_start = trak->sample_to_chunk_table[i].first_chunk; 1648 if (i < trak->sample_to_chunk_count - 1) 1649 chunk_end = trak->sample_to_chunk_table[i + 1].first_chunk; 1650 else 1651 /* if the first chunk is in the last table entry, iterate to the 1652 final chunk number (the number of offsets in stco table) */ 1653 chunk_end = trak->chunk_offset_count + 1; 1654 1655 /* iterate through each sample in a chunk */ 1656 for (j = chunk_start - 1; j < chunk_end - 1; j++) 1657 { 1658 1659 samples_per_chunk = 1660 trak->sample_to_chunk_table[i].samples_per_chunk; 1661 current_offset = trak->chunk_offset_table[j]; 1662 while (samples_per_chunk > 0) 1663 { 1664 1665 /* figure out the offset and size */ 1666 trak->frames[frame_counter].offset = current_offset; 1667 if (trak->sample_size) 1668 { 1669 trak->frames[frame_counter].size = trak->sample_size; 1670 current_offset += trak->sample_size; 1671 } 1672 else 1673 { 1674 trak->frames[frame_counter].size = 1675 trak->sample_size_table[frame_counter]; 1676 current_offset += 1677 trak->sample_size_table[frame_counter]; 1678 } 1679 1680 /* if there is no stss (sample sync) table, make all of the frames 1681 * keyframes; otherwise, clear the keyframe bits for now */ 1682 if (trak->sync_sample_table) 1683 trak->frames[frame_counter].keyframe = 0; 1684 else 1685 trak->frames[frame_counter].keyframe = 1; 1686 1687 /* figure out the pts situation */ 1688 trak->frames[frame_counter].pts = current_pts; 1689 current_pts += 1690 trak->time_to_sample_table[pts_index].duration; 1691 pts_index_countdown--; 1692 /* time to refresh countdown? */ 1693 if (!pts_index_countdown) 1694 { 1695 pts_index++; 1696 pts_index_countdown = 1697 trak->time_to_sample_table[pts_index].count; 1698 } 1699 1700 samples_per_chunk--; 1701 frame_counter++; 1702 } 1703 } 1704 } 1705 1706 /* fill in the keyframe information */ 1707 if (trak->sync_sample_table) 1708 { 1709 for (i = 0; i < trak->sync_sample_count; i++) 1710 trak->frames[trak->sync_sample_table[i] - 1].keyframe = 1; 1711 } 1712 1713 /* initialize edit list considerations */ 1714 edit_list_index = 0; 1715 get_next_edit_list_entry (trak, &edit_list_index, 1716 &edit_list_media_time, &edit_list_duration, 1717 global_timescale); 1718 1719 /* fix up pts information w.r.t. the edit list table */ 1720 edit_list_pts_counter = 0; 1721 for (i = 0; i < trak->frame_count; i++) 1722 { 1723 1724 debug_edit_list (" %d: (before) pts = %lld...", i, 1725 trak->frames[i].pts); 1726 1727 if (trak->frames[i].pts < edit_list_media_time) 1728 trak->frames[i].pts = edit_list_pts_counter; 1729 else 1730 { 1731 if (i < trak->frame_count - 1) 1732 frame_duration = 1733 (trak->frames[i + 1].pts - trak->frames[i].pts); 1734 1735 debug_edit_list ("duration = %lld...", frame_duration); 1736 trak->frames[i].pts = edit_list_pts_counter; 1737 edit_list_pts_counter += frame_duration; 1738 edit_list_duration -= frame_duration; 1739 } 1740 1741 debug_edit_list ("(fixup) pts = %lld...", trak->frames[i].pts); 1742 1743 /* reload media time and duration */ 1744 if (edit_list_duration <= 0) 1745 { 1746 get_next_edit_list_entry (trak, &edit_list_index, 1747 &edit_list_media_time, 1748 &edit_list_duration, 1749 global_timescale); 1750 } 1751 1752 debug_edit_list ("(after) pts = %lld...\n", trak->frames[i].pts); 1753 } 1754 1755 /* compute final pts values */ 1756 for (i = 0; i < trak->frame_count; i++) 1757 { 1758 trak->frames[i].pts *= 90000; 1759 trak->frames[i].pts /= trak->timescale; 1760 debug_edit_list (" final pts for sample %d = %lld\n", i, 1761 trak->frames[i].pts); 1762 } 1763 1764 } 1765 else 1766 { 1767 1768 /* in this case, the total number of frames is equal to the number of 1769 * chunks */ 1770 trak->frame_count = trak->chunk_offset_count; 1771 trak->frames = 1772 (qt_frame *) malloc (trak->frame_count * sizeof (qt_frame)); 1773 if (!trak->frames) 1774 return QT_NO_MEMORY; 1775 1776 if (trak->type == MEDIA_AUDIO) 1777 { 1778 /* iterate through each start chunk in the stsc table */ 1779 for (i = 0; i < trak->sample_to_chunk_count; i++) 1780 { 1781 /* iterate from the first chunk of the current table entry to 1782 * the first chunk of the next table entry */ 1783 chunk_start = trak->sample_to_chunk_table[i].first_chunk; 1784 if (i < trak->sample_to_chunk_count - 1) 1785 chunk_end = trak->sample_to_chunk_table[i + 1].first_chunk; 1786 else 1787 /* if the first chunk is in the last table entry, iterate to the 1788 final chunk number (the number of offsets in stco table) */ 1789 chunk_end = trak->chunk_offset_count + 1; 1790 1791 /* iterate through each sample in a chunk and fill in size and 1792 * pts information */ 1793 for (j = chunk_start - 1; j < chunk_end - 1; j++) 1794 { 1795 1796 /* figure out the pts for this chunk */ 1797 trak->frames[j].pts = audio_frame_counter; 1798 trak->frames[j].pts *= 90000; 1799 trak->frames[j].pts /= trak->timescale; 1800 1801 /* fetch the alleged chunk size according to the QT header */ 1802 trak->frames[j].size = 1803 trak->sample_to_chunk_table[i].samples_per_chunk; 1804 1805 /* the chunk size is actually the audio frame count */ 1806 audio_frame_counter += trak->frames[j].size; 1807 1808 /* compute the actual chunk size */ 1809 trak->frames[j].size = 1810 (trak->frames[j].size * 1811 trak->properties.audio.channels) / 1812 trak->properties.audio.samples_per_frame * 1813 trak->properties.audio.bytes_per_frame; 1814 } 1815 } 1816 } 1817 1818 /* fill in the rest of the information for the audio samples */ 1819 for (i = 0; i < trak->frame_count; i++) 1820 { 1821 trak->frames[i].offset = trak->chunk_offset_table[i]; 1822 trak->frames[i].keyframe = 0; 1823 if (trak->type != MEDIA_AUDIO) 1824 trak->frames[i].pts = 0; 1825 } 1826 } 1827 1828 return QT_OK; 1829 } 1830 1831 /* 1832 * This function takes a pointer to a qt_info structure and a pointer to 1833 * a buffer containing an uncompressed moov atom. When the function 1834 * finishes successfully, qt_info will have a list of qt_frame objects, 1835 * ordered by offset. 1836 */ 1837 static void 1838 parse_moov_atom (qt_info * info, unsigned char *moov_atom, int64_t bandwidth) 1839 { 1840 int i, j; 1841 unsigned int moov_atom_size = BE_32 (&moov_atom[0]); 1842 qt_atom current_atom; 1843 int string_size; 1844 unsigned int max_video_frames = 0; 1845 unsigned int max_audio_frames = 0; 1846 1847 /* make sure this is actually a moov atom */ 1848 if (BE_32 (&moov_atom[4]) != MOOV_ATOM) 1849 { 1850 info->last_error = QT_NO_MOOV_ATOM; 1851 return; 1852 } 1853 1854 /* prowl through the moov atom looking for very specific targets */ 1855 for (i = ATOM_PREAMBLE_SIZE; i < moov_atom_size - 4; i++) 1856 { 1857 current_atom = BE_32 (&moov_atom[i]); 1858 1859 if (current_atom == MVHD_ATOM) 1860 { 1861 parse_mvhd_atom (info, &moov_atom[i - 4]); 1862 if (info->last_error != QT_OK) 1863 return; 1864 i += BE_32 (&moov_atom[i - 4]) - 4; 1865 } 1866 else if (current_atom == TRAK_ATOM) 1867 { 1868 1869 /* create a new trak structure */ 1870 info->trak_count++; 1871 info->traks = (qt_trak *) realloc (info->traks, 1872 info->trak_count * 1873 sizeof (qt_trak)); 1874 1875 parse_trak_atom (&info->traks[info->trak_count - 1], 1876 &moov_atom[i - 4]); 1877 if (info->last_error != QT_OK) 1878 { 1879 info->trak_count--; 1880 return; 1881 } 1882 i += BE_32 (&moov_atom[i - 4]) - 4; 1883 1884 } 1885 else if (current_atom == CPY_ATOM) 1886 { 1887 1888 string_size = BE_16 (&moov_atom[i + 4]) + 1; 1889 info->copyright = realloc (info->copyright, string_size); 1890 strncpy (info->copyright, &moov_atom[i + 8], string_size - 1); 1891 info->copyright[string_size - 1] = 0; 1892 1893 } 1894 else if (current_atom == DES_ATOM) 1895 { 1896 1897 string_size = BE_16 (&moov_atom[i + 4]) + 1; 1898 info->description = realloc (info->description, string_size); 1899 strncpy (info->description, &moov_atom[i + 8], string_size - 1); 1900 info->description[string_size - 1] = 0; 1901 1902 } 1903 else if (current_atom == CMT_ATOM) 1904 { 1905 1906 string_size = BE_16 (&moov_atom[i + 4]) + 1; 1907 info->comment = realloc (info->comment, string_size); 1908 strncpy (info->comment, &moov_atom[i + 8], string_size - 1); 1909 info->comment[string_size - 1] = 0; 1910 1911 } 1912 else if (current_atom == RMDA_ATOM) 1913 { 1914 1915 /* create a new reference structure */ 1916 info->reference_count++; 1917 info->references = (reference_t *) realloc (info->references, 1918 info->reference_count * 1919 sizeof (reference_t)); 1920 1921 parse_reference_atom (&info->references[info->reference_count - 1], 1922 &moov_atom[i - 4], info->base_mrl); 1923 1924 } 1925 } 1926 debug_atom_load (" qt: finished parsing moov atom\n"); 1927 1928 /* build frame tables corresponding to each trak */ 1929 debug_frame_table (" qt: preparing to build %d frame tables\n", 1930 info->trak_count); 1931 for (i = 0; i < info->trak_count; i++) 1932 { 1933 1934 debug_frame_table (" qt: building frame table #%d (%s)\n", i, 1935 (info->traks[i].type == 1936 MEDIA_VIDEO) ? "video" : "audio"); 1937 build_frame_table (&info->traks[i], info->timescale); 1938 1939 /* dump the frame table in debug mode */ 1940 for (j = 0; j < info->traks[i].frame_count; j++) 1941 debug_frame_table (" %d: %8X bytes @ %llX, %lld pts%s\n", 1942 j, 1943 info->traks[i].frames[j].size, 1944 info->traks[i].frames[j].offset, 1945 info->traks[i].frames[j].pts, 1946 (info->traks[i].frames[j]. 1947 keyframe) ? " (keyframe)" : ""); 1948 1949 /* decide which audio trak and which video trak has the most frames */ 1950 if ((info->traks[i].type == MEDIA_VIDEO) && 1951 (info->traks[i].frame_count > max_video_frames)) 1952 { 1953 1954 info->video_trak = i; 1955 max_video_frames = info->traks[i].frame_count; 1956 1957 } 1958 else if ((info->traks[i].type == MEDIA_AUDIO) && 1959 (info->traks[i].frame_count > max_audio_frames)) 1960 { 1961 1962 info->audio_trak = i; 1963 max_audio_frames = info->traks[i].frame_count; 1964 } 1965 } 1966 1967 /* check for references */ 1968 if (info->reference_count > 0) 1969 { 1970 1971 /* init chosen reference to the first entry */ 1972 info->chosen_reference = 0; 1973 1974 /* iterate through 1..n-1 reference entries and decide on the right one */ 1975 for (i = 1; i < info->reference_count; i++) 1976 { 1977 1978 if (info->references[i].qtim_version > 1979 info->references[info->chosen_reference].qtim_version) 1980 info->chosen_reference = i; 1981 else if ((info->references[i].data_rate <= bandwidth) && 1982 (info->references[i].data_rate > 1983 info->references[info->chosen_reference].data_rate)) 1984 info->chosen_reference = i; 1985 } 1986 1987 debug_atom_load 1988 (" qt: chosen reference is ref #%d, qtim version %04X, %lld bps\n URL: %s\n", 1989 info->chosen_reference, 1990 info->references[info->chosen_reference].qtim_version, 1991 info->references[info->chosen_reference].data_rate, 1992 info->references[info->chosen_reference].url); 1993 } 1994 } 1995 1996 static qt_error 1997 open_qt_file (qt_info * info, input_plugin_t * input, int64_t bandwidth) 1998 { 1999 2000 unsigned char *moov_atom = NULL; 2001 off_t moov_atom_offset = -1; 2002 int64_t moov_atom_size = -1; 2003 unsigned char preview[MAX_PREVIEW_SIZE]; 2004 2005 /* zlib stuff */ 2006 z_stream z_state; 2007 int z_ret_code; 2008 unsigned char *unzip_buffer; 2009 2010 /* extract the base MRL if this is a http MRL */ 2011 if (strncmp (input->get_mrl (input), "http://", 7) == 0) 2012 { 2013 2014 char *slash; 2015 2016 /* this will copy a few bytes too many, but no big deal */ 2017 info->base_mrl = strdup (input->get_mrl (input)); 2018 /* terminate the string after the last slash character */ 2019 slash = strrchr (info->base_mrl, '/'); 2020 if (slash) 2021 *(slash + 1) = '\0'; 2022 } 2023 2024 if ((input->get_capabilities (input) & INPUT_CAP_SEEKABLE)) 2025 find_moov_atom (input, &moov_atom_offset, &moov_atom_size); 2026 else 2027 { 2028 input->get_optional_data (input, preview, INPUT_OPTIONAL_DATA_PREVIEW); 2029 if (BE_32 (&preview[4]) != MOOV_ATOM) 2030 { 2031 info->last_error = QT_NO_MOOV_ATOM; 2032 return info->last_error; 2033 } 2034 moov_atom_offset = 0; 2035 moov_atom_size = BE_32 (&preview[0]); 2036 } 2037 2038 if (moov_atom_offset == -1) 2039 { 2040 info->last_error = QT_NO_MOOV_ATOM; 2041 return info->last_error; 2042 } 2043 info->moov_first_offset = moov_atom_offset; 2044 2045 moov_atom = (unsigned char *) malloc (moov_atom_size); 2046 if (moov_atom == NULL) 2047 { 2048 info->last_error = QT_NO_MEMORY; 2049 return info->last_error; 2050 } 2051 2052 /* seek to the start of moov atom */ 2053 if (input->seek (input, info->moov_first_offset, SEEK_SET) != 2054 info->moov_first_offset) 2055 { 2056 free (moov_atom); 2057 info->last_error = QT_FILE_READ_ERROR; 2058 return info->last_error; 2059 } 2060 if (input->read (input, moov_atom, moov_atom_size) != moov_atom_size) 2061 { 2062 free (moov_atom); 2063 info->last_error = QT_FILE_READ_ERROR; 2064 return info->last_error; 2065 } 2066 2067 /* check if moov is compressed */ 2068 if (BE_32 (&moov_atom[12]) == CMOV_ATOM) 2069 { 2070 2071 info->compressed_header = 1; 2072 2073 z_state.next_in = &moov_atom[0x28]; 2074 z_state.avail_in = moov_atom_size - 0x28; 2075 z_state.avail_out = BE_32 (&moov_atom[0x24]); 2076 unzip_buffer = (unsigned char *) malloc (BE_32 (&moov_atom[0x24])); 2077 if (!unzip_buffer) 2078 { 2079 free (moov_atom); 2080 info->last_error = QT_NO_MEMORY; 2081 return info->last_error; 2082 } 2083 2084 z_state.next_out = unzip_buffer; 2085 z_state.zalloc = (alloc_func) 0; 2086 z_state.zfree = (free_func) 0; 2087 z_state.opaque = (voidpf) 0; 2088 2089 z_ret_code = inflateInit (&z_state); 2090 if (Z_OK != z_ret_code) 2091 { 2092 free (unzip_buffer); 2093 free (moov_atom); 2094 info->last_error = QT_ZLIB_ERROR; 2095 return info->last_error; 2096 } 2097 2098 z_ret_code = inflate (&z_state, Z_NO_FLUSH); 2099 if ((z_ret_code != Z_OK) && (z_ret_code != Z_STREAM_END)) 2100 { 2101 free (unzip_buffer); 2102 free (moov_atom); 2103 info->last_error = QT_ZLIB_ERROR; 2104 return info->last_error; 2105 } 2106 2107 z_ret_code = inflateEnd (&z_state); 2108 if (Z_OK != z_ret_code) 2109 { 2110 free (unzip_buffer); 2111 free (moov_atom); 2112 info->last_error = QT_ZLIB_ERROR; 2113 return info->last_error; 2114 } 2115 2116 /* replace the compressed moov atom with the decompressed atom */ 2117 free (moov_atom); 2118 moov_atom = unzip_buffer; 2119 moov_atom_size = BE_32 (&moov_atom[0]); 2120 } 2121 2122 if (!moov_atom) 2123 { 2124 info->last_error = QT_NO_MOOV_ATOM; 2125 return info->last_error; 2126 } 2127 2128 /* write moov atom to disk if debugging option is turned on */ 2129 dump_moov_atom (moov_atom, moov_atom_size); 2130 2131 /* take apart the moov atom */ 2132 parse_moov_atom (info, moov_atom, bandwidth); 2133 if (info->last_error != QT_OK) 2134 { 2135 free (moov_atom); 2136 return info->last_error; 2137 } 2138 2139 free (moov_atom); 2140 2141 return QT_OK; 2142 } 2143 2144 /********************************************************************** 2145 * xine demuxer functions 2146 **********************************************************************/ 2147 2148 static int 2149 demux_qt_send_chunk (demux_plugin_t * this_gen) 2150 { 2151 2152 demux_qt_t *this = (demux_qt_t *) this_gen; 2153 buf_element_t *buf = NULL; 2154 unsigned int i, j; 2155 unsigned int remaining_sample_bytes; 2156 int frame_duration; 2157 int first_buf; 2158 qt_trak *video_trak = NULL; 2159 qt_trak *audio_trak = NULL; 2160 int dispatch_audio; /* boolean for deciding which trak to dispatch */ 2161 int64_t pts_diff; 2162 xine_event_t uevent; 2163 xine_mrl_reference_data_t *data; 2164 2165 /* check if it's time to send a reference up to the UI */ 2166 if (this->qt->chosen_reference != -1) 2167 { 2168 2169 uevent.type = XINE_EVENT_MRL_REFERENCE; 2170 uevent.stream = this->stream; 2171 uevent.data_length = 2172 strlen (this->qt->references[this->qt->chosen_reference].url) + 2173 sizeof (xine_mrl_reference_data_t); 2174 data = malloc (uevent.data_length); 2175 uevent.data = data; 2176 strcpy (data->mrl, 2177 this->qt->references[this->qt->chosen_reference].url); 2178 data->alternative = 0; 2179 xine_event_send (this->stream, &uevent); 2180 2181 this->status = DEMUX_FINISHED; 2182 return this->status; 2183 } 2184 2185 if (this->qt->video_trak != -1) 2186 { 2187 video_trak = &this->qt->traks[this->qt->video_trak]; 2188 } 2189 if (this->qt->audio_trak != -1) 2190 { 2191 audio_trak = &this->qt->traks[this->qt->audio_trak]; 2192 } 2193 2194 if (!audio_trak && !video_trak) 2195 { 2196 /* something is really wrong if this case is reached */ 2197 this->status = DEMUX_FINISHED; 2198 return this->status; 2199 } 2200 2201 /* check if it is time to seek */ 2202 if (this->qt->seek_flag) 2203 { 2204 this->qt->seek_flag = 0; 2205 2206 /* if audio is present, send pts of current audio frame, otherwise 2207 * send current video frame pts */ 2208 if (audio_trak) 2209 xine_demux_control_newpts (this->stream, 2210 audio_trak->frames[audio_trak-> 2211 current_frame].pts, 2212 BUF_FLAG_SEEK); 2213 else 2214 xine_demux_control_newpts (this->stream, 2215 video_trak->frames[video_trak-> 2216 current_frame].pts, 2217 BUF_FLAG_SEEK); 2218 } 2219 2220 /* Decide the trak from which to dispatch a frame. Policy: Dispatch 2221 * the frames in offset order as much as possible. If the pts difference 2222 * between the current frames from the audio and video traks is too 2223 * wide, make an exception. This exception deals with non-interleaved 2224 * Quicktime files. */ 2225 if (!audio_trak) 2226 { 2227 2228 /* only video is present */ 2229 dispatch_audio = 0; 2230 if (video_trak->current_frame >= video_trak->frame_count) 2231 { 2232 this->status = DEMUX_FINISHED; 2233 return this->status; 2234 } 2235 2236 } 2237 else if (!video_trak) 2238 { 2239 2240 /* only audio is present */ 2241 dispatch_audio = 1; 2242 if (audio_trak->current_frame >= audio_trak->frame_count) 2243 { 2244 this->status = DEMUX_FINISHED; 2245 return this->status; 2246 } 2247 2248 } 2249 else 2250 { 2251 2252 /* both audio and video are present; start making some tough choices */ 2253 2254 /* check the frame count limits */ 2255 if ((audio_trak->current_frame >= audio_trak->frame_count) && 2256 (video_trak->current_frame >= video_trak->frame_count)) 2257 { 2258 2259 this->status = DEMUX_FINISHED; 2260 return this->status; 2261 2262 } 2263 else if (video_trak->current_frame >= video_trak->frame_count) 2264 { 2265 2266 dispatch_audio = 1; 2267 2268 } 2269 else if (audio_trak->current_frame >= audio_trak->frame_count) 2270 { 2271 2272 dispatch_audio = 0; 2273 2274 } 2275 else 2276 { 2277 2278 /* at this point, it is certain that both traks still have frames 2279 * yet to be dispatched */ 2280 pts_diff = audio_trak->frames[audio_trak->current_frame].pts; 2281 pts_diff -= video_trak->frames[video_trak->current_frame].pts; 2282 2283 if (pts_diff > MAX_PTS_DIFF) 2284 { 2285 /* if diff is +max_diff, audio is too far ahead of video */ 2286 dispatch_audio = 0; 2287 } 2288 else if (pts_diff < -MAX_PTS_DIFF) 2289 { 2290 /* if diff is -max_diff, video is too far ahead of audio */ 2291 dispatch_audio = 1; 2292 } 2293 else if (audio_trak->frames[audio_trak->current_frame].offset < 2294 video_trak->frames[video_trak->current_frame].offset) 2295 { 2296 /* pts diff is not too wide, decide based on earlier offset */ 2297 dispatch_audio = 1; 2298 } 2299 else 2300 { 2301 dispatch_audio = 0; 2302 } 2303 } 2304 } 2305 2306 if (!dispatch_audio) 2307 { 2308 i = video_trak->current_frame++; 2309 remaining_sample_bytes = video_trak->frames[i].size; 2310 this->input->seek (this->input, video_trak->frames[i].offset, SEEK_SET); 2311 2312 if (i + 1 < video_trak->frame_count) 2313 { 2314 /* frame duration is the pts diff between this video frame and 2315 * the next video frame */ 2316 frame_duration = video_trak->frames[i + 1].pts; 2317 frame_duration -= video_trak->frames[i].pts; 2318 } 2319 else 2320 { 2321 /* give the last frame some fixed duration */ 2322 frame_duration = 12000; 2323 } 2324 2325 /* Due to the edit lists, some successive frames have the same pts 2326 * which would ordinarily cause frame_duration to be 0 which can 2327 * cause DIV-by-0 errors in the engine. Perform this little trick 2328 * to compensate. */ 2329 if (!frame_duration) 2330 { 2331 frame_duration = 1; 2332 video_trak->properties.video.edit_list_compensation++; 2333 } 2334 else 2335 { 2336 frame_duration -= 2337 video_trak->properties.video.edit_list_compensation; 2338 video_trak->properties.video.edit_list_compensation = 0; 2339 } 2340 2341 this->stream->stream_info[XINE_STREAM_INFO_FRAME_DURATION] = 2342 frame_duration; 2343 2344 debug_video_demux 2345 (" qt: sending off video frame %d from offset 0x%llX, %d bytes, %lld pts\n", 2346 i, video_trak->frames[i].offset, video_trak->frames[i].size, 2347 video_trak->frames[i].pts); 2348 2349 while (remaining_sample_bytes) 2350 { 2351 buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); 2352 buf->type = video_trak->properties.video.codec_buftype; 2353 buf->extra_info->input_pos = 2354 video_trak->frames[i].offset - this->data_start; 2355 buf->extra_info->input_length = this->data_size; 2356 buf->extra_info->input_time = video_trak->frames[i].pts / 90; 2357 buf->pts = video_trak->frames[i].pts; 2358 2359 buf->decoder_flags |= BUF_FLAG_FRAMERATE; 2360 buf->decoder_info[0] = frame_duration; 2361 2362 if (remaining_sample_bytes > buf->max_size) 2363 buf->size = buf->max_size; 2364 else 2365 buf->size = remaining_sample_bytes; 2366 remaining_sample_bytes -= buf->size; 2367 2368 if (this->input->read (this->input, buf->content, buf->size) != 2369 buf->size) 2370 { 2371 buf->free_buffer (buf); 2372 this->status = DEMUX_FINISHED; 2373 break; 2374 } 2375 2376 if (video_trak->frames[i].keyframe) 2377 buf->decoder_flags |= BUF_FLAG_KEYFRAME; 2378 if (!remaining_sample_bytes) 2379 buf->decoder_flags |= BUF_FLAG_FRAME_END; 2380 2381 this->video_fifo->put (this->video_fifo, buf); 2382 } 2383 2384 } 2385 else 2386 { 2387 /* load an audio sample and packetize it */ 2388 i = audio_trak->current_frame++; 2389 2390 /* only go through with this procedure if audio_fifo exists */ 2391 if (!this->audio_fifo) 2392 return this->status; 2393 2394 remaining_sample_bytes = audio_trak->frames[i].size; 2395 this->input->seek (this->input, audio_trak->frames[i].offset, SEEK_SET); 2396 2397 debug_audio_demux 2398 (" qt: sending off audio frame %d from offset 0x%llX, %d bytes, %lld pts\n", 2399 i, audio_trak->frames[i].offset, audio_trak->frames[i].size, 2400 audio_trak->frames[i].pts); 2401 2402 first_buf = 1; 2403 while (remaining_sample_bytes) 2404 { 2405 buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); 2406 buf->type = audio_trak->properties.audio.codec_buftype; 2407 buf->extra_info->input_pos = 2408 audio_trak->frames[i].offset - this->data_start; 2409 buf->extra_info->input_length = this->data_size; 2410 /* The audio chunk is often broken up into multiple 8K buffers when 2411 * it is sent to the audio decoder. Only attach the proper timestamp 2412 * to the first buffer. This is for the linear PCM decoder which 2413 * turns around and sends out audio buffers as soon as they are 2414 * received. If 2 or more consecutive audio buffers are dispatched to 2415 * the audio out unit, the engine will compensate with pops. */ 2416 if ((buf->type == BUF_AUDIO_LPCM_BE) || 2417 (buf->type == BUF_AUDIO_LPCM_LE)) 2418 { 2419 if (first_buf) 2420 { 2421 buf->extra_info->input_time = 2422 audio_trak->frames[i].pts / 90; 2423 buf->pts = audio_trak->frames[i].pts; 2424 first_buf = 0; 2425 } 2426 else 2427 { 2428 buf->extra_info->input_time = 0; 2429 buf->pts = 0; 2430 } 2431 } 2432 else 2433 { 2434 buf->extra_info->input_time = audio_trak->frames[i].pts / 90; 2435 buf->pts = audio_trak->frames[i].pts; 2436 } 2437 2438 if (remaining_sample_bytes > buf->max_size) 2439 buf->size = buf->max_size; 2440 else 2441 buf->size = remaining_sample_bytes; 2442 remaining_sample_bytes -= buf->size; 2443 2444 if (this->input->read (this->input, buf->content, buf->size) != 2445 buf->size) 2446 { 2447 buf->free_buffer (buf); 2448 this->status = DEMUX_FINISHED; 2449 break; 2450 } 2451 2452 /* Special case alert: If this is signed, 8-bit data, transform 2453 * the data to unsigned. */ 2454 if ((audio_trak->properties.audio.bits == 8) && 2455 ((audio_trak->properties.audio.codec_fourcc == TWOS_FOURCC) || 2456 (audio_trak->properties.audio.codec_fourcc == SOWT_FOURCC))) 2457 for (j = 0; j < buf->size; j++) 2458 buf->content[j] += 0x80; 2459 2460 if (!remaining_sample_bytes) 2461 { 2462 buf->decoder_flags |= BUF_FLAG_FRAME_END; 2463 } 2464 2465 this->audio_fifo->put (this->audio_fifo, buf); 2466 } 2467 } 2468 2469 return this->status; 2470 } 2471 2472 static void 2473 demux_qt_send_headers (demux_plugin_t * this_gen) 2474 { 2475 2476 demux_qt_t *this = (demux_qt_t *) this_gen; 2477 buf_element_t *buf; 2478 qt_trak *video_trak = NULL; 2479 qt_trak *audio_trak = NULL; 2480 2481 /* for deciding data start and data size */ 2482 int64_t first_video_offset = -1; 2483 int64_t last_video_offset = -1; 2484 int64_t first_audio_offset = -1; 2485 int64_t last_audio_offset = -1; 2486 2487 this->video_fifo = this->stream->video_fifo; 2488 this->audio_fifo = this->stream->audio_fifo; 2489 2490 this->status = DEMUX_OK; 2491 2492 /* figure out where the data begins and ends */ 2493 if (this->qt->video_trak != -1) 2494 { 2495 video_trak = &this->qt->traks[this->qt->video_trak]; 2496 first_video_offset = video_trak->frames[0].offset; 2497 last_video_offset = 2498 video_trak->frames[video_trak->frame_count - 1].size + 2499 video_trak->frames[video_trak->frame_count - 1].offset; 2500 } 2501 if (this->qt->audio_trak != -1) 2502 { 2503 audio_trak = &this->qt->traks[this->qt->audio_trak]; 2504 first_audio_offset = audio_trak->frames[0].offset; 2505 last_audio_offset = 2506 audio_trak->frames[audio_trak->frame_count - 1].size + 2507 audio_trak->frames[audio_trak->frame_count - 1].offset; 2508 } 2509 2510 if (first_video_offset < first_audio_offset) 2511 this->data_start = first_video_offset; 2512 else 2513 this->data_start = first_audio_offset; 2514 2515 if (last_video_offset > last_audio_offset) 2516 this->data_size = last_video_offset - this->data_size; 2517 else 2518 this->data_size = last_audio_offset - this->data_size; 2519 2520 /* sort out the A/V information */ 2521 if (this->qt->video_trak != -1) 2522 { 2523 2524 this->bih.biSize = sizeof (this->bih); 2525 this->bih.biWidth = video_trak->properties.video.width; 2526 this->bih.biHeight = video_trak->properties.video.height; 2527 this->bih.biBitCount = video_trak->properties.video.depth; 2528 2529 this->bih.biCompression = video_trak->properties.video.codec_fourcc; 2530 video_trak->properties.video.codec_buftype = 2531 fourcc_to_buf_video (this->bih.biCompression); 2532 2533 /* hack: workaround a fourcc clash! 'mpg4' is used by MS and Sorenson 2534 * mpeg4 codecs (they are not compatible). 2535 */ 2536 if (video_trak->properties.video.codec_buftype == BUF_VIDEO_MSMPEG4_V1) 2537 video_trak->properties.video.codec_buftype = BUF_VIDEO_MPEG4; 2538 2539 if (!video_trak->properties.video.codec_buftype && 2540 video_trak->properties.video.codec_fourcc) 2541 video_trak->properties.video.codec_buftype = BUF_VIDEO_UNKNOWN; 2542 2543 this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 1; 2544 this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = 2545 this->bih.biWidth; 2546 this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = 2547 this->bih.biHeight; 2548 this->stream->stream_info[XINE_STREAM_INFO_VIDEO_FOURCC] = 2549 video_trak->properties.video.codec_fourcc; 2550 2551 } 2552 else 2553 { 2554 2555 memset (&this->bih, 0, sizeof (this->bih)); 2556 this->bih.biSize = sizeof (this->bih); 2557 this->stream->stream_info[XINE_STREAM_INFO_HAS_VIDEO] = 0; 2558 this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = 0; 2559 this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = 0; 2560 this->stream->stream_info[XINE_STREAM_INFO_VIDEO_FOURCC] = 0; 2561 2562 } 2563 2564 if (this->qt->audio_trak != -1) 2565 { 2566 2567 audio_trak->properties.audio.codec_buftype = 2568 formattag_to_buf_audio (audio_trak->properties.audio.codec_fourcc); 2569 2570 if (!audio_trak->properties.audio.codec_buftype && 2571 audio_trak->properties.audio.codec_fourcc) 2572 audio_trak->properties.audio.codec_buftype = BUF_AUDIO_UNKNOWN; 2573 2574 this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 1; 2575 this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 2576 audio_trak->properties.audio.channels; 2577 this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = 2578 audio_trak->properties.audio.sample_rate; 2579 this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = 2580 audio_trak->properties.audio.bits; 2581 this->stream->stream_info[XINE_STREAM_INFO_AUDIO_FOURCC] = 2582 audio_trak->properties.audio.codec_fourcc; 2583 2584 } 2585 else 2586 { 2587 2588 this->stream->stream_info[XINE_STREAM_INFO_HAS_AUDIO] = 0; 2589 this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 0; 2590 this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = 0; 2591 this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = 0; 2592 this->stream->stream_info[XINE_STREAM_INFO_AUDIO_FOURCC] = 0; 2593 2594 } 2595 2596 /* copy over the meta information like artist and title */ 2597 if (this->qt->copyright) 2598 this->stream->meta_info[XINE_META_INFO_ARTIST] = 2599 strdup (this->qt->copyright); 2600 if (this->qt->description) 2601 this->stream->meta_info[XINE_META_INFO_TITLE] = 2602 strdup (this->qt->description); 2603 if (this->qt->comment) 2604 this->stream->meta_info[XINE_META_INFO_COMMENT] = 2605 strdup (this->qt->comment); 2606 2607 /* send start buffers */ 2608 xine_demux_control_start (this->stream); 2609 2610 /* send init info to decoders */ 2611 if (video_trak && (video_trak->properties.video.codec_buftype)) 2612 { 2613 buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); 2614 buf->decoder_flags = BUF_FLAG_HEADER; 2615 buf->decoder_info[0] = 0; 2616 /* initial video step; not necessary since each QT frame has its own 2617 * duration, but set it non-zero as a matter of custom */ 2618 buf->decoder_info[1] = 3000; 2619 memcpy (buf->content, &this->bih, sizeof (this->bih)); 2620 buf->size = sizeof (this->bih); 2621 buf->type = video_trak->properties.video.codec_buftype; 2622 this->video_fifo->put (this->video_fifo, buf); 2623 2624 /* send header info to decoder. some mpeg4 streams need this */ 2625 if (video_trak->decoder_config) 2626 { 2627 buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); 2628 buf->type = video_trak->properties.video.codec_buftype; 2629 buf->size = video_trak->decoder_config_len; 2630 buf->content = video_trak->decoder_config; 2631 this->video_fifo->put (this->video_fifo, buf); 2632 } 2633 2634 /* send off the palette, if there is one */ 2635 if (video_trak->properties.video.palette_count) 2636 { 2637 buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); 2638 buf->decoder_flags = BUF_FLAG_SPECIAL; 2639 buf->decoder_info[1] = BUF_SPECIAL_PALETTE; 2640 buf->decoder_info[2] = video_trak->properties.video.palette_count; 2641 buf->decoder_info_ptr[2] = &video_trak->properties.video.palette; 2642 buf->size = 0; 2643 buf->type = video_trak->properties.video.codec_buftype; 2644 this->video_fifo->put (this->video_fifo, buf); 2645 } 2646 2647 /* send stsd to the decoder */ 2648 buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); 2649 buf->decoder_flags = BUF_FLAG_SPECIAL; 2650 buf->decoder_info[1] = BUF_SPECIAL_STSD_ATOM; 2651 buf->decoder_info[2] = video_trak->stsd_size; 2652 buf->decoder_info_ptr[2] = video_trak->stsd; 2653 buf->size = 0; 2654 buf->type = video_trak->properties.video.codec_buftype; 2655 this->video_fifo->put (this->video_fifo, buf); 2656 } 2657 2658 if ((this->qt->audio_trak != -1) && 2659 (audio_trak->properties.audio.codec_buftype) && this->audio_fifo) 2660 { 2661 2662 buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); 2663 buf->type = audio_trak->properties.audio.codec_buftype; 2664 buf->decoder_flags = BUF_FLAG_HEADER; 2665 buf->decoder_info[0] = 0; 2666 buf->decoder_info[1] = audio_trak->properties.audio.sample_rate; 2667 buf->decoder_info[2] = audio_trak->properties.audio.bits; 2668 buf->decoder_info[3] = audio_trak->properties.audio.channels; 2669 buf->content = (void *) &audio_trak->properties.audio.wave; 2670 buf->size = sizeof (audio_trak->properties.audio.wave); 2671 this->audio_fifo->put (this->audio_fifo, buf); 2672 2673 if (audio_trak->decoder_config) 2674 { 2675 buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); 2676 buf->type = audio_trak->properties.audio.codec_buftype; 2677 buf->size = 0; 2678 buf->decoder_flags = BUF_FLAG_SPECIAL; 2679 buf->decoder_info[1] = BUF_SPECIAL_DECODER_CONFIG; 2680 buf->decoder_info[2] = audio_trak->decoder_config_len; 2681 buf->decoder_info_ptr[2] = audio_trak->decoder_config; 2682 this->audio_fifo->put (this->audio_fifo, buf); 2683 } 2684 2685 /* send stsd to the decoder */ 2686 buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); 2687 buf->decoder_flags = BUF_FLAG_SPECIAL; 2688 buf->decoder_info[1] = BUF_SPECIAL_STSD_ATOM; 2689 buf->decoder_info[2] = audio_trak->stsd_size; 2690 buf->decoder_info_ptr[2] = audio_trak->stsd; 2691 buf->size = 0; 2692 buf->type = audio_trak->properties.audio.codec_buftype; 2693 this->audio_fifo->put (this->audio_fifo, buf); 2694 2695 } 2696 } 2697 2698 /* support function that performs a binary seek on a trak; returns the 2699 * demux status */ 2700 static int 2701 binary_seek (qt_trak * trak, off_t start_pos, int start_time) 2702 { 2703 2704 int best_index; 2705 int left, middle, right; 2706 int found; 2707 2708 /* perform a binary search on the trak, testing the offset 2709 * boundaries first; offset request has precedent over time request */ 2710 if (start_pos) 2711 { 2712 if (start_pos <= trak->frames[0].offset) 2713 best_index = 0; 2714 else if (start_pos >= trak->frames[trak->frame_count - 1].offset) 2715 return DEMUX_FINISHED; 2716 else 2717 { 2718 left = 0; 2719 right = trak->frame_count - 1; 2720 found = 0; 2721 2722 while (!found) 2723 { 2724 middle = (left + right + 1) / 2; 2725 if ((start_pos >= trak->frames[middle].offset) && 2726 (start_pos < trak->frames[middle + 1].offset)) 2727 { 2728 found = 1; 2729 } 2730 else if (start_pos < trak->frames[middle].offset) 2731 { 2732 right = middle - 1; 2733 } 2734 else 2735 { 2736 left = middle; 2737 } 2738 } 2739 2740 best_index = middle; 2741 } 2742 } 2743 else 2744 { 2745 int64_t pts = 90000 * start_time; 2746 2747 if (pts <= trak->frames[0].pts) 2748 best_index = 0; 2749 else if (pts >= trak->frames[trak->frame_count - 1].pts) 2750 return DEMUX_FINISHED; 2751 else 2752 { 2753 left = 0; 2754 right = trak->frame_count - 1; 2755 do 2756 { 2757 middle = (left + right + 1) / 2; 2758 if (pts < trak->frames[middle].pts) 2759 { 2760 right = (middle - 1); 2761 } 2762 else 2763 { 2764 left = middle; 2765 } 2766 } 2767 while (left < right); 2768 2769 best_index = left; 2770 } 2771 } 2772 2773 trak->current_frame = best_index; 2774 return DEMUX_OK; 2775 } 2776 2777 static int 2778 demux_qt_seek (demux_plugin_t * this_gen, off_t start_pos, int start_time) 2779 { 2780 2781 demux_qt_t *this = (demux_qt_t *) this_gen; 2782 qt_trak *video_trak = NULL; 2783 qt_trak *audio_trak = NULL; 2784 2785 int64_t keyframe_pts; 2786 2787 /* short-circuit any attempts to seek in a non-seekable stream, including 2788 * seeking in the forward direction; this may change later */ 2789 if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) == 0) 2790 { 2791 this->qt->seek_flag = 1; 2792 this->status = DEMUX_OK; 2793 return this->status; 2794 } 2795 2796 /* if there is a video trak, position it as close as possible to the 2797 * requested position */ 2798 if (this->qt->video_trak != -1) 2799 { 2800 video_trak = &this->qt->traks[this->qt->video_trak]; 2801 this->status = binary_seek (video_trak, start_pos, start_time); 2802 if (this->status != DEMUX_OK) 2803 return this->status; 2804 } 2805 2806 if (this->qt->audio_trak != -1) 2807 { 2808 audio_trak = &this->qt->traks[this->qt->audio_trak]; 2809 this->status = binary_seek (audio_trak, start_pos, start_time); 2810 if (this->status != DEMUX_OK) 2811 return this->status; 2812 } 2813 2814 /* search back in the video trak for the nearest keyframe */ 2815 if (video_trak) 2816 while (video_trak->current_frame) 2817 { 2818 if (video_trak->frames[video_trak->current_frame].keyframe) 2819 { 2820 break; 2821 } 2822 video_trak->current_frame--; 2823 } 2824 2825 /* not done yet; now that the nearest keyframe has been found, seek 2826 * back to the first audio frame that has a pts less than or equal to 2827 * that of the keyframe; do not go through with this process there is 2828 * no video trak */ 2829 if (audio_trak && video_trak) 2830 { 2831 keyframe_pts = video_trak->frames[video_trak->current_frame].pts; 2832 while (audio_trak->current_frame) 2833 { 2834 if (audio_trak->frames[audio_trak->current_frame].pts < 2835 keyframe_pts) 2836 { 2837 break; 2838 } 2839 audio_trak->current_frame--; 2840 } 2841 } 2842 2843 this->qt->seek_flag = 1; 2844 this->status = DEMUX_OK; 2845 2846 /* 2847 * do only flush if already running (seeking). 2848 * otherwise decoder_config is flushed too. 2849 */ 2850 if (this->stream->demux_thread_running) 2851 xine_demux_flush_engine (this->stream); 2852 2853 return this->status; 2854 } 2855 2856 static void 2857 demux_qt_dispose (demux_plugin_t * this_gen) 2858 { 2859 demux_qt_t *this = (demux_qt_t *) this_gen; 2860 2861 free_qt_info (this->qt); 2862 free (this); 2863 } 2864 2865 static int 2866 demux_qt_get_status (demux_plugin_t * this_gen) 2867 { 2868 demux_qt_t *this = (demux_qt_t *) this_gen; 2869 2870 return this->status; 2871 } 2872 2873 static int 2874 demux_qt_get_stream_length (demux_plugin_t * this_gen) 2875 { 2876 2877 demux_qt_t *this = (demux_qt_t *) this_gen; 2878 2879 return (int) ((int64_t) 1000 * this->qt->duration / this->qt->timescale); 2880 } 2881 2882 static uint32_t 2883 demux_qt_get_capabilities (demux_plugin_t * this_gen) 2884 { 2885 return DEMUX_CAP_NOCAP; 2886 } 2887 2888 static int 2889 demux_qt_get_optional_data (demux_plugin_t * this_gen, 2890 void *data, int data_type) 2891 { 2892 return DEMUX_OPTIONAL_UNSUPPORTED; 2893 } 2894 2895 static demux_plugin_t * 2896 open_plugin (demux_class_t * class_gen, xine_stream_t * stream, 2897 input_plugin_t * input_gen) 2898 { 2899 2900 input_plugin_t *input = (input_plugin_t *) input_gen; 2901 demux_qt_t *this; 2902 xine_cfg_entry_t entry; 2903 2904 if ((input->get_capabilities (input) & INPUT_CAP_BLOCK)) 2905 { 2906 return NULL; 2907 } 2908 2909 this = xine_xmalloc (sizeof (demux_qt_t)); 2910 this->stream = stream; 2911 this->input = input; 2912 2913 /* fetch bandwidth config */ 2914 this->bandwidth = 0x7FFFFFFFFFFFFFFF; /* assume infinite bandwidth */ 2915 if (xine_config_lookup_entry (stream->xine, "input.mms_network_bandwidth", 2916 &entry)) 2917 { 2918 if ((entry.num_value >= 0) && (entry.num_value <= 11)) 2919 this->bandwidth = bandwidths[entry.num_value]; 2920 } 2921 2922 this->demux_plugin.send_headers = demux_qt_send_headers; 2923 this->demux_plugin.send_chunk = demux_qt_send_chunk; 2924 this->demux_plugin.seek = demux_qt_seek; 2925 this->demux_plugin.dispose = demux_qt_dispose; 2926 this->demux_plugin.get_status = demux_qt_get_status; 2927 this->demux_plugin.get_stream_length = demux_qt_get_stream_length; 2928 this->demux_plugin.get_video_frame = NULL; 2929 this->demux_plugin.got_video_frame_cb = NULL; 2930 this->demux_plugin.get_capabilities = demux_qt_get_capabilities; 2931 this->demux_plugin.get_optional_data = demux_qt_get_optional_data; 2932 this->demux_plugin.demux_class = class_gen; 2933 2934 this->status = DEMUX_FINISHED; 2935 2936 switch (stream->content_detection_method) 2937 { 2938 2939 case METHOD_BY_CONTENT: 2940 2941 if (!is_qt_file (this->input)) 2942 { 2943 free (this); 2944 return NULL; 2945 } 2946 if ((this->qt = create_qt_info ()) == NULL) 2947 { 2948 free (this); 2949 return NULL; 2950 } 2951 if (open_qt_file (this->qt, this->input, this->bandwidth) != QT_OK) 2952 { 2953 free_qt_info (this->qt); 2954 free (this); 2955 return NULL; 2956 } 2957 2958 break; 2959 2960 case METHOD_BY_EXTENSION: 2961 { 2962 char *ending, *mrl; 2963 2964 mrl = input->get_mrl (input); 2965 2966 ending = strrchr (mrl, '.'); 2967 2968 if (!ending) 2969 { 2970 free (this); 2971 return NULL; 2972 } 2973 2974 if (strncasecmp (ending, ".mov", 4) && 2975 strncasecmp (ending, ".qt", 3) && strncasecmp (ending, ".mp4", 4)) 2976 { 2977 free (this); 2978 return NULL; 2979 } 2980 } 2981 2982 /* we want to fall through here */ 2983 case METHOD_EXPLICIT: 2984 { 2985 2986 if (!is_qt_file (this->input)) 2987 { 2988 free (this); 2989 return NULL; 2990 } 2991 if ((this->qt = create_qt_info ()) == NULL) 2992 { 2993 free (this); 2994 return NULL; 2995 } 2996 if (open_qt_file (this->qt, this->input, this->bandwidth) != QT_OK) 2997 { 2998 free_qt_info (this->qt); 2999 free (this); 3000 return NULL; 3001 } 3002 } 3003 break; 3004 3005 default: 3006 free (this); 3007 return NULL; 3008 } 3009 3010 strncpy (this->last_mrl, input->get_mrl (input), 1024); 3011 3012 return &this->demux_plugin; 3013 } 3014 3015 static char * 3016 get_description (demux_class_t * this_gen) 3017 { 3018 return "Apple Quicktime (MOV) and MPEG-4 demux plugin"; 3019 } 3020 3021 static char * 3022 get_identifier (demux_class_t * this_gen) 3023 { 3024 return "MOV/MPEG-4"; 3025 } 3026 3027 static char * 3028 get_extensions (demux_class_t * this_gen) 3029 { 3030 return "mov qt mp4"; 3031 } 3032 3033 static char * 3034 get_mimetypes (demux_class_t * this_gen) 3035 { 3036 return "video/quicktime: mov,qt: Quicktime animation;" 3037 "video/x-quicktime: mov,qt: Quicktime animation;" 3038 "application/x-quicktimeplayer: qtl: Quicktime list"; 3039 } 3040 3041 static void 3042 class_dispose (demux_class_t * this_gen) 3043 { 3044 3045 demux_qt_class_t *this = (demux_qt_class_t *) this_gen; 3046 3047 free (this); 3048 } 3049 3050 static void * 3051 init_plugin (xine_t * xine, void *data) 3052 { 3053 3054 demux_qt_class_t *this; 3055 3056 this = xine_xmalloc (sizeof (demux_qt_class_t)); 3057 this->config = xine->config; 3058 this->xine = xine; 3059 3060 this->demux_class.open_plugin = open_plugin; 3061 this->demux_class.get_description = get_description; 3062 this->demux_class.get_identifier = get_identifier; 3063 this->demux_class.get_mimetypes = get_mimetypes; 3064 this->demux_class.get_extensions = get_extensions; 3065 this->demux_class.dispose = class_dispose; 3066 3067 return this; 3068 } 3069 3070 /* 3071 * exported plugin catalog entry 3072 */ 3073 3074 plugin_info_t xine_plugin_info[] = { 3075 /* type, API, "name", version, special_info, init_function */ 3076 {PLUGIN_DEMUX, 20, "quicktime", XINE_VERSION_CODE, NULL, init_plugin} 3077 , 3078 {PLUGIN_NONE, 0, "", 0, NULL, NULL} 3079 };