Mercurial > mplayer.hg
comparison libmpdemux/demux_real.c @ 36545:f0e92381681d
Add support for files with MLTI chunks.
Fixes 06.rm and 08_lect_01.rm from FFmpeg trac #2152
Fixes also files from ftp://ftp.aduni.org/videos/
The patch has these limitations:
- no multirate files with MLTI chunks
- no mixed files (eg. MLTI for audio but not for video)
- no MLTI for video together with non-ra audio (eg. ralf)
- only DATA v0 (no v1, versions greater than 1 should not exist)
Files with these feature shuld not really exist anyway.
Also video MLTI files with only one stream are supported but untested
author | rtogni |
---|---|
date | Sun, 19 Jan 2014 15:12:46 +0000 |
parents | 139f2b064ef9 |
children | b72ae5f17e3a |
comparison
equal
deleted
inserted
replaced
36544:cc8102c4ca83 | 36545:f0e92381681d |
---|---|
1 /* | 1 /* |
2 * Real parser & demuxer | 2 * Real parser & demuxer |
3 * copyright (C) 2001 Alex Beregszaszi | 3 * copyright (C) 2001 Alex Beregszaszi |
4 * copyright (C) 2005, 2006 Roberto Togni | 4 * copyright (C) 2005, 2006, 2014 Roberto Togni |
5 * based on FFmpeg's libav/rm.c | 5 * based on FFmpeg's libav/rm.c |
6 * | 6 * |
7 * audio codecs: (supported by RealPlayer8 for Linux) | 7 * audio codecs: (supported by RealPlayer8 for Linux) |
8 * DNET - RealAudio 3.0, really it's AC3 in swapped-byteorder | 8 * DNET - RealAudio 3.0, really it's AC3 in swapped-byteorder |
9 * SIPR - SiproLab's audio codec, ACELP decoder working with MPlayer, | 9 * SIPR - SiproLab's audio codec, ACELP decoder working with MPlayer, |
52 #include "demux_real.h" | 52 #include "demux_real.h" |
53 | 53 |
54 //#define mp_dbg(mod,lev, args... ) mp_msg_c((mod<<8)|lev, ## args ) | 54 //#define mp_dbg(mod,lev, args... ) mp_msg_c((mod<<8)|lev, ## args ) |
55 | 55 |
56 #define MAX_STREAMS 32 | 56 #define MAX_STREAMS 32 |
57 #define MAX_MLTIIDX 16 | |
57 | 58 |
58 static unsigned char sipr_swaps[38][2]={ | 59 static unsigned char sipr_swaps[38][2]={ |
59 {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68}, | 60 {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68}, |
60 {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46}, | 61 {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46}, |
61 {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56}, | 62 {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56}, |
79 int index_table_size[MAX_STREAMS]; | 80 int index_table_size[MAX_STREAMS]; |
80 int index_malloc_size[MAX_STREAMS]; | 81 int index_malloc_size[MAX_STREAMS]; |
81 int data_chunk_offset; | 82 int data_chunk_offset; |
82 int num_of_packets; | 83 int num_of_packets; |
83 int current_packet; | 84 int current_packet; |
85 int streams_in_file; | |
84 | 86 |
85 // need for seek | 87 // need for seek |
86 int audio_need_keyframe; | 88 int audio_need_keyframe; |
87 int video_after_seek; | 89 int video_after_seek; |
88 | 90 |
112 int a_num_of_packets; ///< Number of audio packets | 114 int a_num_of_packets; ///< Number of audio packets |
113 int v_num_of_packets; ///< Number of video packets | 115 int v_num_of_packets; ///< Number of video packets |
114 int a_bitrate; ///< Audio bitrate | 116 int a_bitrate; ///< Audio bitrate |
115 int v_bitrate; ///< Video bitrate | 117 int v_bitrate; ///< Video bitrate |
116 int stream_switch; ///< Flag used to switch audio/video demuxing | 118 int stream_switch; ///< Flag used to switch audio/video demuxing |
119 | |
120 /** | |
121 * Used to demux MLTI files | |
122 */ | |
123 int is_mlti; ///< != 0 for MLTI files | |
124 unsigned int mp2rm_streamid[MAX_STREAMS]; ///< Convert Mplayer stream_id to rm stream id | |
125 unsigned int rm2mp[MAX_STREAMS][MAX_MLTIIDX]; ///< Convert rm stream id and mlti index to Mplayer stream_id | |
117 | 126 |
118 /** | 127 /** |
119 * Used to reorder audio data | 128 * Used to reorder audio data |
120 */ | 129 */ |
121 unsigned int intl_id[MAX_STREAMS]; ///< interleaver id, per stream | 130 unsigned int intl_id[MAX_STREAMS]; ///< interleaver id, per stream |
570 { | 579 { |
571 real_priv_t *priv = demuxer->priv; | 580 real_priv_t *priv = demuxer->priv; |
572 demux_stream_t *ds = NULL; | 581 demux_stream_t *ds = NULL; |
573 int len; | 582 int len; |
574 unsigned int timestamp; | 583 unsigned int timestamp; |
575 int stream_id; | 584 int rm_stream_id, mp_stream_id; |
576 #ifdef CRACK_MATRIX | 585 #ifdef CRACK_MATRIX |
577 int i; | 586 int i; |
578 #endif | 587 #endif |
579 int flags; | 588 int flags; |
580 int version; | 589 int version; |
581 int reserved; | 590 int pk_group;; |
582 demux_packet_t *dp; | 591 demux_packet_t *dp; |
583 int x, sps, cfs, sph, spc, w; | 592 int x, sps, cfs, sph, spc, w; |
584 int audioreorder_getnextpk = 0; | 593 int audioreorder_getnextpk = 0; |
585 | 594 |
586 // Don't demux video if video codec init failed | 595 // Don't demux video if video codec init failed |
628 if (len == -256){ /* EOF */ | 637 if (len == -256){ /* EOF */ |
629 // printf("len==-256!\n"); | 638 // printf("len==-256!\n"); |
630 return 0; | 639 return 0; |
631 } | 640 } |
632 if (len < 12){ | 641 if (len < 12){ |
642 unsigned int idx_streamid; | |
633 mp_msg(MSGT_DEMUX, MSGL_V,"%08X: packet v%d len=%d \n",(int)demuxer->filepos,(int)version,(int)len); | 643 mp_msg(MSGT_DEMUX, MSGL_V,"%08X: packet v%d len=%d \n",(int)demuxer->filepos,(int)version,(int)len); |
634 mp_msg(MSGT_DEMUX, MSGL_WARN,"bad packet len (%d)\n", len); | 644 mp_msg(MSGT_DEMUX, MSGL_WARN,"bad packet len (%d)\n", len); |
635 if ((unsigned)demuxer->video->id < MAX_STREAMS) { | 645 if ((unsigned)demuxer->video->id < MAX_STREAMS) { |
636 if (priv->current_vpacket + 1 < priv->index_table_size[demuxer->video->id]) { | 646 idx_streamid = priv->is_mlti ? priv->mp2rm_streamid[demuxer->video->id] : demuxer->video->id; |
637 stream_seek(demuxer->stream, priv->index_table[demuxer->video->id][++priv->current_vpacket].offset); | 647 if (priv->current_vpacket + 1 < priv->index_table_size[idx_streamid]) { |
648 stream_seek(demuxer->stream, priv->index_table[idx_streamid][++priv->current_vpacket].offset); | |
638 } | 649 } |
639 } else if ((unsigned)demuxer->audio->id < MAX_STREAMS) { | 650 } else if ((unsigned)demuxer->audio->id < MAX_STREAMS) { |
640 if (priv->current_apacket + 1 < priv->index_table_size[demuxer->audio->id]) { | 651 idx_streamid = priv->is_mlti ? priv->mp2rm_streamid[demuxer->audio->id] : demuxer->video->id; |
641 stream_seek(demuxer->stream, priv->index_table[demuxer->audio->id][++priv->current_apacket].offset); | 652 if (priv->current_apacket + 1 < priv->index_table_size[idx_streamid]) { |
653 stream_seek(demuxer->stream, priv->index_table[idx_streamid][++priv->current_apacket].offset); | |
642 } | 654 } |
643 } | 655 } |
644 continue; //goto loop; | 656 continue; //goto loop; |
645 } | 657 } |
646 | 658 |
647 stream_id = stream_read_word(demuxer->stream); | 659 rm_stream_id = stream_read_word(demuxer->stream); |
648 timestamp = stream_read_dword(demuxer->stream); | 660 timestamp = stream_read_dword(demuxer->stream); |
649 reserved = stream_read_char(demuxer->stream); | 661 pk_group = stream_read_char(demuxer->stream); |
650 flags = stream_read_char(demuxer->stream); | 662 flags = stream_read_char(demuxer->stream); |
651 /* flags: */ | 663 /* flags: */ |
652 /* 0x1 - reliable */ | 664 /* 0x1 - reliable */ |
653 /* 0x2 - keyframe */ | 665 /* 0x2 - keyframe */ |
654 | 666 |
655 if (version == 1) { | 667 if (version == 1) { |
656 int tmp; | 668 int tmp; |
657 tmp = stream_read_char(demuxer->stream); | 669 tmp = stream_read_char(demuxer->stream); |
658 mp_msg(MSGT_DEMUX, MSGL_DBG2,"Version: %d, skipped byte is %d\n", version, tmp); | 670 mp_msg(MSGT_DEMUX, MSGL_DBG2,"Version: %d, skipped byte is %d\n", version, tmp); |
659 len--; | 671 len--; |
672 if (priv->is_mlti) | |
673 mp_msg(MSGT_DEMUX, MSGL_WARN,"MLTI file with v1 DATA, expect problems! Please contact Mplayer developers.\n"); | |
660 } | 674 } |
661 | 675 |
662 if (flags & 2) | 676 if (flags & 2) |
663 add_index_item(demuxer, stream_id, timestamp, demuxer->filepos); | 677 add_index_item(demuxer, rm_stream_id, timestamp, demuxer->filepos); |
664 | 678 |
665 // printf("%08X: packet v%d len=%4d id=%d pts=%6d rvd=%d flags=%d \n", | 679 // printf("%08X: packet v%d len=%4d id=%d pts=%6d rvd=%d flags=%d \n", |
666 // (int)demuxer->filepos,(int)version,(int)len, stream_id, | 680 // (int)demuxer->filepos,(int)version,(int)len, stream_id, |
667 // (int) timestamp, reserved, flags); | 681 // (int) timestamp, reserved, flags); |
668 | 682 |
669 mp_dbg(MSGT_DEMUX,MSGL_DBG2, "\npacket#%d: pos: 0x%0x, len: %d, id: %d, pts: %u, flags: %x rvd:%d\n", | 683 mp_dbg(MSGT_DEMUX,MSGL_DBG2, "\npacket#%d: pos: 0x%0x, len: %d, rm_id: %d, pts: %u, flags: %x grp:%d\n", |
670 priv->current_packet, (int)demuxer->filepos, len, stream_id, timestamp, flags, reserved); | 684 priv->current_packet, (int)demuxer->filepos, len, rm_stream_id, timestamp, flags, pk_group); |
671 | 685 |
672 priv->current_packet++; | 686 priv->current_packet++; |
673 len -= 12; | 687 len -= 12; |
674 | 688 |
675 // printf("s_id=%d aid=%d vid=%d \n",stream_id,demuxer->audio->id,demuxer->video->id); | 689 // printf("s_id=%d aid=%d vid=%d \n",stream_id,demuxer->audio->id,demuxer->video->id); |
676 | 690 |
691 // Map rm stream id and packet group to MPlayer stream aid or vid if file is MLTI | |
692 if (priv->is_mlti && rm_stream_id < MAX_STREAMS && (pk_group>>1) < MAX_MLTIIDX) | |
693 mp_stream_id = priv->rm2mp[rm_stream_id][(pk_group>>1)-1]; | |
694 else | |
695 mp_stream_id = rm_stream_id; | |
696 | |
677 /* check stream_id: */ | 697 /* check stream_id: */ |
678 | 698 |
679 if(demuxer->audio->id==stream_id){ | 699 if(demuxer->audio->id==mp_stream_id){ |
680 if (priv->audio_need_keyframe == 1&& flags != 0x2) | 700 if (priv->audio_need_keyframe == 1&& flags != 0x2) |
681 goto discard; | 701 goto discard; |
682 got_audio: | 702 got_audio: |
683 ds=demuxer->audio; | 703 ds=demuxer->audio; |
684 mp_dbg(MSGT_DEMUX,MSGL_DBG2, "packet is audio (id: %d)\n", stream_id); | 704 mp_dbg(MSGT_DEMUX,MSGL_DBG2, "packet is audio (mp_id: %d)\n", mp_stream_id); |
685 | 705 |
686 if (flags & 2) { | 706 if (flags & 2) { |
687 priv->sub_packet_cnt = 0; | 707 priv->sub_packet_cnt = 0; |
688 audioreorder_getnextpk = 0; | 708 audioreorder_getnextpk = 0; |
689 } | 709 } |
719 dp->pos = demuxer->filepos; | 739 dp->pos = demuxer->filepos; |
720 ds_add_packet(ds, dp); | 740 ds_add_packet(ds, dp); |
721 } | 741 } |
722 return 1; | 742 return 1; |
723 } | 743 } |
724 if ((priv->intl_id[stream_id] == mmioFOURCC('I', 'n', 't', '4')) || | 744 if ((priv->intl_id[demuxer->audio->id] == mmioFOURCC('I', 'n', 't', '4')) || |
725 (priv->intl_id[stream_id] == mmioFOURCC('g', 'e', 'n', 'r')) || | 745 (priv->intl_id[demuxer->audio->id] == mmioFOURCC('g', 'e', 'n', 'r')) || |
726 (priv->intl_id[stream_id] == mmioFOURCC('s', 'i', 'p', 'r'))) { | 746 (priv->intl_id[demuxer->audio->id] == mmioFOURCC('s', 'i', 'p', 'r'))) { |
727 sps = priv->sub_packet_size[stream_id]; | 747 sps = priv->sub_packet_size[demuxer->audio->id]; |
728 sph = priv->sub_packet_h[stream_id]; | 748 sph = priv->sub_packet_h[demuxer->audio->id]; |
729 cfs = priv->coded_framesize[stream_id]; | 749 cfs = priv->coded_framesize[demuxer->audio->id]; |
730 w = priv->audiopk_size[stream_id]; | 750 w = priv->audiopk_size[demuxer->audio->id]; |
731 spc = priv->sub_packet_cnt; | 751 spc = priv->sub_packet_cnt; |
732 switch (priv->intl_id[stream_id]) { | 752 switch (priv->intl_id[demuxer->audio->id]) { |
733 case mmioFOURCC('I', 'n', 't', '4'): | 753 case mmioFOURCC('I', 'n', 't', '4'): |
734 if (len < cfs * sph/2) | 754 if (len < cfs * sph/2) |
735 goto discard; | 755 goto discard; |
736 for (x = 0; x < sph / 2; x++) | 756 for (x = 0; x < sph / 2; x++) |
737 stream_read(demuxer->stream, priv->audio_buf + x * 2 * w + spc * cfs, cfs); | 757 stream_read(demuxer->stream, priv->audio_buf + x * 2 * w + spc * cfs, cfs); |
842 | 862 |
843 } // codec_id check, codec default case | 863 } // codec_id check, codec default case |
844 } | 864 } |
845 // we will not use audio index if we use -idx and have a video | 865 // we will not use audio index if we use -idx and have a video |
846 if(((!demuxer->video->sh && index_mode == 2) || priv->is_multirate) && (unsigned)demuxer->audio->id < MAX_STREAMS) { | 866 if(((!demuxer->video->sh && index_mode == 2) || priv->is_multirate) && (unsigned)demuxer->audio->id < MAX_STREAMS) { |
847 while (priv->current_apacket + 1 < priv->index_table_size[demuxer->audio->id] && | 867 while (priv->current_apacket + 1 < priv->index_table_size[rm_stream_id] && |
848 timestamp > priv->index_table[demuxer->audio->id][priv->current_apacket].timestamp) { | 868 timestamp > priv->index_table[rm_stream_id][priv->current_apacket].timestamp) { |
849 priv->current_apacket += 1; | 869 priv->current_apacket += 1; |
850 priv->stream_switch = 1; | 870 priv->stream_switch = 1; |
851 } | 871 } |
852 if (priv->stream_switch) | 872 if (priv->stream_switch) |
853 priv->audio_curpos = stream_tell(demuxer->stream); | 873 priv->audio_curpos = stream_tell(demuxer->stream); |
858 continue; | 878 continue; |
859 | 879 |
860 return 1; | 880 return 1; |
861 } | 881 } |
862 | 882 |
863 if(demuxer->video->id==stream_id){ | 883 if(demuxer->video->id==mp_stream_id){ |
864 got_video: | 884 got_video: |
865 ds=demuxer->video; | 885 ds=demuxer->video; |
866 mp_dbg(MSGT_DEMUX,MSGL_DBG2, "packet is video (id: %d)\n", stream_id); | 886 mp_dbg(MSGT_DEMUX,MSGL_DBG2, "packet is video (mp_id: %d)\n", mp_stream_id); |
867 | 887 |
868 // parse video chunk: | 888 // parse video chunk: |
869 { | 889 { |
870 // we need a more complicated, 2nd level demuxing, as the video | 890 // we need a more complicated, 2nd level demuxing, as the video |
871 // frames are stored fragmented in the video chunks :( | 891 // frames are stored fragmented in the video chunks :( |
1039 mp_msg(MSGT_DEMUX, MSGL_WARN,"\n******** !!!!!!!! BUG!! len=%d !!!!!!!!!!! ********\n",len); | 1059 mp_msg(MSGT_DEMUX, MSGL_WARN,"\n******** !!!!!!!! BUG!! len=%d !!!!!!!!!!! ********\n",len); |
1040 if(len>0) stream_skip(demuxer->stream, len); | 1060 if(len>0) stream_skip(demuxer->stream, len); |
1041 } | 1061 } |
1042 } | 1062 } |
1043 if ((unsigned)demuxer->video->id < MAX_STREAMS) { | 1063 if ((unsigned)demuxer->video->id < MAX_STREAMS) { |
1044 while (priv->current_vpacket + 1 < priv->index_table_size[demuxer->video->id] && | 1064 while (priv->current_vpacket + 1 < priv->index_table_size[rm_stream_id] && |
1045 timestamp > priv->index_table[demuxer->video->id][priv->current_vpacket + 1].timestamp) { | 1065 timestamp > priv->index_table[rm_stream_id][priv->current_vpacket + 1].timestamp) { |
1046 priv->current_vpacket += 1; | 1066 priv->current_vpacket += 1; |
1047 priv->stream_switch = 1; | 1067 priv->stream_switch = 1; |
1048 } | 1068 } |
1049 if (priv->stream_switch) | 1069 if (priv->stream_switch) |
1050 priv->video_curpos = stream_tell(demuxer->stream); | 1070 priv->video_curpos = stream_tell(demuxer->stream); |
1051 } | 1071 } |
1052 | 1072 |
1053 return 1; | 1073 return 1; |
1054 } | 1074 } |
1055 | 1075 |
1056 if((unsigned)stream_id<MAX_STREAMS){ | 1076 if((unsigned)rm_stream_id<MAX_STREAMS){ |
1057 | 1077 if(demuxer->audio->id==-1 && demuxer->a_streams[mp_stream_id]){ |
1058 if(demuxer->audio->id==-1 && demuxer->a_streams[stream_id]){ | 1078 sh_audio_t *sh = demuxer->a_streams[mp_stream_id]; |
1059 sh_audio_t *sh = demuxer->a_streams[stream_id]; | 1079 demuxer->audio->id=mp_stream_id; |
1060 demuxer->audio->id=stream_id; | |
1061 sh->ds=demuxer->audio; | 1080 sh->ds=demuxer->audio; |
1062 demuxer->audio->sh=sh; | 1081 demuxer->audio->sh=sh; |
1063 priv->audio_buf = calloc(priv->sub_packet_h[demuxer->audio->id], priv->audiopk_size[demuxer->audio->id]); | 1082 priv->audio_buf = calloc(priv->sub_packet_h[demuxer->audio->id], priv->audiopk_size[demuxer->audio->id]); |
1064 priv->audio_timestamp = calloc(priv->sub_packet_h[demuxer->audio->id], sizeof(double)); | 1083 priv->audio_timestamp = calloc(priv->sub_packet_h[demuxer->audio->id], sizeof(double)); |
1065 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected RM audio ID = %d\n",stream_id); | 1084 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected RM audio ID = %d (rm id %d)\n",mp_stream_id, rm_stream_id); |
1066 goto got_audio; | 1085 goto got_audio; |
1067 } | 1086 } |
1068 | 1087 |
1069 if(demuxer->video->id==-1 && demuxer->v_streams[stream_id]){ | 1088 if(demuxer->video->id==-1 && demuxer->v_streams[mp_stream_id]){ |
1070 sh_video_t *sh = demuxer->v_streams[stream_id]; | 1089 sh_video_t *sh = demuxer->v_streams[mp_stream_id]; |
1071 demuxer->video->id=stream_id; | 1090 demuxer->video->id=mp_stream_id; |
1072 sh->ds=demuxer->video; | 1091 sh->ds=demuxer->video; |
1073 demuxer->video->sh=sh; | 1092 demuxer->video->sh=sh; |
1074 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected RM video ID = %d\n",stream_id); | 1093 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected RM video ID = %d (rm id %d)\n",mp_stream_id, rm_stream_id); |
1075 goto got_video; | 1094 goto got_video; |
1076 } | 1095 } |
1077 | 1096 |
1078 } | 1097 } |
1079 | 1098 |
1080 mp_msg(MSGT_DEMUX,MSGL_DBG2, "unknown stream id (%d)\n", stream_id); | 1099 mp_msg(MSGT_DEMUX,MSGL_DBG2, "unknown stream id (%d)\n", rm_stream_id); |
1081 discard: | 1100 discard: |
1082 stream_skip(demuxer->stream, len); | 1101 stream_skip(demuxer->stream, len); |
1083 }// goto loop; | 1102 }// goto loop; |
1084 return 0; | 1103 return 0; |
1085 } | 1104 } |
1138 stream_skip(demuxer->stream, 4); /* preroll */ | 1157 stream_skip(demuxer->stream, 4); /* preroll */ |
1139 priv->index_chunk_offset = stream_read_dword(demuxer->stream); | 1158 priv->index_chunk_offset = stream_read_dword(demuxer->stream); |
1140 mp_msg(MSGT_DEMUX,MSGL_V,"First index chunk offset: 0x%x\n", priv->index_chunk_offset); | 1159 mp_msg(MSGT_DEMUX,MSGL_V,"First index chunk offset: 0x%x\n", priv->index_chunk_offset); |
1141 priv->data_chunk_offset = stream_read_dword(demuxer->stream)+10; | 1160 priv->data_chunk_offset = stream_read_dword(demuxer->stream)+10; |
1142 mp_msg(MSGT_DEMUX,MSGL_V,"First data chunk offset: 0x%x\n", priv->data_chunk_offset); | 1161 mp_msg(MSGT_DEMUX,MSGL_V,"First data chunk offset: 0x%x\n", priv->data_chunk_offset); |
1143 stream_skip(demuxer->stream, 2); /* nb streams */ | 1162 priv->streams_in_file = stream_read_word(demuxer->stream); |
1163 mp_msg(MSGT_DEMUX,MSGL_V,"Number of streams in file: %d\n", priv->streams_in_file); | |
1144 #if 0 | 1164 #if 0 |
1145 stream_skip(demuxer->stream, 2); /* flags */ | 1165 stream_skip(demuxer->stream, 2); /* flags */ |
1146 #else | 1166 #else |
1147 { | 1167 { |
1148 int flags = stream_read_word(demuxer->stream); | 1168 int flags = stream_read_word(demuxer->stream); |
1216 int codec_data_size; | 1236 int codec_data_size; |
1217 int codec_pos; | 1237 int codec_pos; |
1218 int tmp; | 1238 int tmp; |
1219 int len; | 1239 int len; |
1220 char *descr, *mimet = NULL; | 1240 char *descr, *mimet = NULL; |
1221 | |
1222 stream_id = stream_read_word(demuxer->stream); | 1241 stream_id = stream_read_word(demuxer->stream); |
1223 mp_msg(MSGT_DEMUX,MSGL_V,"Found new stream (id: %d)\n", stream_id); | 1242 mp_msg(MSGT_DEMUX,MSGL_V,"Found new stream (id: %d)\n", stream_id); |
1224 | 1243 |
1225 stream_skip(demuxer->stream, 4); /* max bitrate */ | 1244 stream_skip(demuxer->stream, 4); /* max bitrate */ |
1226 bitrate = stream_read_dword(demuxer->stream); /* avg bitrate */ | 1245 bitrate = stream_read_dword(demuxer->stream); /* avg bitrate */ |
1252 #define stream_skip(st,siz) { int i; for(i=0;i<siz;i++) mp_msg(MSGT_DEMUX,MSGL_V," %02X",stream_read_char(st)); mp_msg(MSGT_DEMUX,MSGL_V,"\n");} | 1271 #define stream_skip(st,siz) { int i; for(i=0;i<siz;i++) mp_msg(MSGT_DEMUX,MSGL_V," %02X",stream_read_char(st)); mp_msg(MSGT_DEMUX,MSGL_V,"\n");} |
1253 #endif | 1272 #endif |
1254 | 1273 |
1255 if (!strncmp(mimet,"audio/",6)) { | 1274 if (!strncmp(mimet,"audio/",6)) { |
1256 if (strstr(mimet,"x-pn-realaudio") || strstr(mimet,"x-pn-multirate-realaudio")) { | 1275 if (strstr(mimet,"x-pn-realaudio") || strstr(mimet,"x-pn-multirate-realaudio")) { |
1276 int num_mlti, mlti_cnt, ra_size; | |
1257 tmp = stream_read_dword(demuxer->stream); | 1277 tmp = stream_read_dword(demuxer->stream); |
1278 if (tmp == MKTAG('I', 'T', 'L', 'M')) // MLTI chunk in audio | |
1279 { | |
1280 int num_streams, stream_cnt; | |
1281 mp_msg(MSGT_DEMUX,MSGL_V,"MLTI chunk in audio.\n"); | |
1282 num_streams = stream_read_word(demuxer->stream); | |
1283 for (stream_cnt = 0; stream_cnt < num_streams; stream_cnt++) | |
1284 stream_skip(demuxer->stream, 2); // MDPR index, one per stream | |
1285 num_mlti = stream_read_word(demuxer->stream); | |
1286 if (num_mlti != 1) { | |
1287 mp_msg(MSGT_DEMUX,MSGL_V,"Found MLTI in audio with %d substreams.\n", num_mlti); | |
1288 priv->is_mlti = 1; | |
1289 } else | |
1290 mp_msg(MSGT_DEMUX,MSGL_V,"Found MLTI in audio with 1 substreams. Ingnoring\n", num_mlti); | |
1291 if (num_mlti > MAX_MLTIIDX) { | |
1292 mp_msg(MSGT_DEMUX,MSGL_ERR,"Too many (%d) MLTI audio, truncating; expect problems. Please report to Mplayer developers.\n", num_mlti); | |
1293 num_mlti = MAX_MLTIIDX - 1; // Limit to max MLTI | |
1294 } | |
1295 ra_size = stream_read_dword(demuxer->stream); // Size of the following .ra chunk | |
1296 tmp = stream_read_dword(demuxer->stream); | |
1297 } else { | |
1298 num_mlti = 1; | |
1299 ra_size = codec_data_size; | |
1300 } | |
1301 for (mlti_cnt = 0; mlti_cnt < num_mlti; mlti_cnt++) { | |
1302 if (mlti_cnt) { | |
1303 ra_size = stream_read_dword(demuxer->stream); // Size of the following .ra chunk | |
1304 tmp = stream_read_dword(demuxer->stream); | |
1305 } | |
1258 if (tmp != MKTAG(0xfd, 'a', 'r', '.')) | 1306 if (tmp != MKTAG(0xfd, 'a', 'r', '.')) |
1259 { | 1307 { |
1260 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: can't find .ra in codec data\n"); | 1308 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: can't find .ra in codec data\n"); |
1309 stream_skip(demuxer->stream, ra_size - 4); | |
1261 } else { | 1310 } else { |
1262 /* audio header */ | 1311 /* audio header */ |
1263 sh_audio_t *sh = new_sh_audio(demuxer, stream_id, NULL); | 1312 int aid = priv->is_mlti ? priv->streams_in_file + a_streams + v_streams : stream_id; |
1313 sh_audio_t *sh = new_sh_audio(demuxer, aid, NULL); | |
1264 char buf[128]; /* for codec name */ | 1314 char buf[128]; /* for codec name */ |
1265 int frame_size; | 1315 int frame_size; |
1266 int sub_packet_size; | 1316 int sub_packet_size; |
1267 int sub_packet_h; | 1317 int sub_packet_h; |
1268 int version; | 1318 int version; |
1270 int coded_frame_size; | 1320 int coded_frame_size; |
1271 int codecdata_length; | 1321 int codecdata_length; |
1272 int i; | 1322 int i; |
1273 char *buft; | 1323 char *buft; |
1274 int hdr_size; | 1324 int hdr_size; |
1275 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "real", stream_id); | 1325 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "real", aid); |
1326 priv->mp2rm_streamid[aid] = stream_id; | |
1327 priv->rm2mp[stream_id][mlti_cnt] = aid; | |
1328 mp_msg(MSGT_DEMUX,MSGL_V,"Mplayer aid %d is rm stream %d with MDPR index %d\n", aid, stream_id, mlti_cnt); | |
1276 mp_msg(MSGT_DEMUX,MSGL_V,"Found audio stream!\n"); | 1329 mp_msg(MSGT_DEMUX,MSGL_V,"Found audio stream!\n"); |
1277 version = stream_read_word(demuxer->stream); | 1330 version = stream_read_word(demuxer->stream); |
1278 mp_msg(MSGT_DEMUX,MSGL_V,"version: %d\n", version); | 1331 mp_msg(MSGT_DEMUX,MSGL_V,"version: %d\n", version); |
1279 if (version == 3) { | 1332 if (version == 3) { |
1280 stream_skip(demuxer->stream, 2); | 1333 stream_skip(demuxer->stream, 2); |
1353 sh->samplerate, sh->channels); | 1406 sh->samplerate, sh->channels); |
1354 | 1407 |
1355 if (version == 5) | 1408 if (version == 5) |
1356 { | 1409 { |
1357 stream_read(demuxer->stream, buf, 4); // interleaver id | 1410 stream_read(demuxer->stream, buf, 4); // interleaver id |
1358 priv->intl_id[stream_id] = MKTAG(buf[0], buf[1], buf[2], buf[3]); | 1411 priv->intl_id[aid] = MKTAG(buf[0], buf[1], buf[2], buf[3]); |
1359 stream_read(demuxer->stream, buf, 4); // fourcc | 1412 stream_read(demuxer->stream, buf, 4); // fourcc |
1360 buf[4] = 0; | 1413 buf[4] = 0; |
1361 } | 1414 } |
1362 else | 1415 else |
1363 { | 1416 { |
1364 /* Interleaver id */ | 1417 /* Interleaver id */ |
1365 get_str(1, demuxer, buf, sizeof(buf)); | 1418 get_str(1, demuxer, buf, sizeof(buf)); |
1366 priv->intl_id[stream_id] = MKTAG(buf[0], buf[1], buf[2], buf[3]); | 1419 priv->intl_id[aid] = MKTAG(buf[0], buf[1], buf[2], buf[3]); |
1367 /* Codec FourCC */ | 1420 /* Codec FourCC */ |
1368 get_str(1, demuxer, buf, sizeof(buf)); | 1421 get_str(1, demuxer, buf, sizeof(buf)); |
1369 } | 1422 } |
1370 } | 1423 } |
1371 | 1424 |
1407 goto skip_this_chunk; | 1460 goto skip_this_chunk; |
1408 } | 1461 } |
1409 sh->wf->cbSize = codecdata_length; | 1462 sh->wf->cbSize = codecdata_length; |
1410 sh->wf = realloc(sh->wf, sizeof(*sh->wf)+sh->wf->cbSize); | 1463 sh->wf = realloc(sh->wf, sizeof(*sh->wf)+sh->wf->cbSize); |
1411 stream_read(demuxer->stream, ((char*)(sh->wf+1)), codecdata_length); // extras | 1464 stream_read(demuxer->stream, ((char*)(sh->wf+1)), codecdata_length); // extras |
1412 if (priv->intl_id[stream_id] == MKTAG('g', 'e', 'n', 'r')) | 1465 if (priv->intl_id[aid] == MKTAG('g', 'e', 'n', 'r')) |
1413 sh->wf->nBlockAlign = sub_packet_size; | 1466 sh->wf->nBlockAlign = sub_packet_size; |
1414 else | 1467 else |
1415 sh->wf->nBlockAlign = coded_frame_size; | 1468 sh->wf->nBlockAlign = coded_frame_size; |
1416 | 1469 |
1417 break; | 1470 break; |
1436 default: | 1489 default: |
1437 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Unknown (%s)\n", buf); | 1490 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Unknown (%s)\n", buf); |
1438 } | 1491 } |
1439 | 1492 |
1440 // Interleaver setup | 1493 // Interleaver setup |
1441 priv->sub_packet_size[stream_id] = sub_packet_size; | 1494 priv->sub_packet_size[aid] = sub_packet_size; |
1442 priv->sub_packet_h[stream_id] = sub_packet_h; | 1495 priv->sub_packet_h[aid] = sub_packet_h; |
1443 priv->coded_framesize[stream_id] = coded_frame_size; | 1496 priv->coded_framesize[aid] = coded_frame_size; |
1444 priv->audiopk_size[stream_id] = frame_size; | 1497 priv->audiopk_size[aid] = frame_size; |
1445 | 1498 |
1446 sh->wf->wFormatTag = sh->format; | 1499 sh->wf->wFormatTag = sh->format; |
1447 | 1500 |
1448 mp_msg(MSGT_DEMUX,MSGL_V,"audio fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format); | 1501 mp_msg(MSGT_DEMUX,MSGL_V,"audio fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format); |
1449 if ( mp_msg_test(MSGT_DEMUX,MSGL_V) ) | 1502 if ( mp_msg_test(MSGT_DEMUX,MSGL_V) ) |
1467 ++a_streams; | 1520 ++a_streams; |
1468 | 1521 |
1469 #ifdef stream_skip | 1522 #ifdef stream_skip |
1470 #undef stream_skip | 1523 #undef stream_skip |
1471 #endif | 1524 #endif |
1472 } | 1525 } // .ra |
1526 } // MLTI | |
1473 } else if (strstr(mimet,"X-MP3-draft-00")) { | 1527 } else if (strstr(mimet,"X-MP3-draft-00")) { |
1474 sh_audio_t *sh = new_sh_audio(demuxer, stream_id, NULL); | 1528 sh_audio_t *sh = new_sh_audio(demuxer, stream_id, NULL); |
1475 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "real", stream_id); | 1529 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "real", stream_id); |
1476 | 1530 |
1477 /* Emulate WAVEFORMATEX struct: */ | 1531 /* Emulate WAVEFORMATEX struct: */ |
1516 } else { | 1570 } else { |
1517 mp_msg(MSGT_DEMUX,MSGL_V,"Unknown audio stream format\n"); | 1571 mp_msg(MSGT_DEMUX,MSGL_V,"Unknown audio stream format\n"); |
1518 } | 1572 } |
1519 } else if (!strncmp(mimet,"video/",6)) { | 1573 } else if (!strncmp(mimet,"video/",6)) { |
1520 if (strstr(mimet,"x-pn-realvideo") || strstr(mimet,"x-pn-multirate-realvideo")) { | 1574 if (strstr(mimet,"x-pn-realvideo") || strstr(mimet,"x-pn-multirate-realvideo")) { |
1521 stream_skip(demuxer->stream, 4); // VIDO length, same as codec_data_size | 1575 int num_mlti, mlti_cnt, vido_size, vido_pos; |
1522 tmp = stream_read_dword(demuxer->stream); | 1576 tmp = stream_read_dword(demuxer->stream); |
1577 if (tmp == MKTAG('I', 'T', 'L', 'M')) // MLTI chunk in video | |
1578 { | |
1579 int num_streams, stream_cnt; | |
1580 mp_msg(MSGT_DEMUX,MSGL_V,"MLTI chunk in video.\n"); | |
1581 num_streams = stream_read_word(demuxer->stream); | |
1582 for (stream_cnt = 0; stream_cnt < num_streams; stream_cnt++) | |
1583 stream_skip(demuxer->stream, 2); // MDPR index, one per stream | |
1584 num_mlti = stream_read_word(demuxer->stream); | |
1585 if (num_mlti != 1) { | |
1586 mp_msg(MSGT_DEMUX,MSGL_V,"Found MLTI in video with %d substreams.\n", num_mlti); | |
1587 priv->is_mlti = 1; | |
1588 } else | |
1589 mp_msg(MSGT_DEMUX,MSGL_V,"Found MLTI in audio with 1 substreams. Ingnoring\n", num_mlti); | |
1590 if (num_mlti > MAX_MLTIIDX) { | |
1591 mp_msg(MSGT_DEMUX,MSGL_ERR,"Too many (%d) MLTI video, truncating; expect problems. Please report to Mplayer developers.\n", num_mlti); | |
1592 num_mlti = MAX_MLTIIDX - 1; // Limit to max MLTI | |
1593 } | |
1594 vido_size = stream_read_dword(demuxer->stream); // Size of the following .vido chunk | |
1595 vido_pos = stream_tell(demuxer->stream);; | |
1596 stream_skip(demuxer->stream, 4); | |
1597 tmp = stream_read_dword(demuxer->stream); | |
1598 priv->is_mlti = 1; | |
1599 } else { | |
1600 num_mlti = 1; | |
1601 vido_size = codec_data_size; | |
1602 vido_pos = codec_pos; | |
1603 tmp = stream_read_dword(demuxer->stream); | |
1604 } | |
1605 for (mlti_cnt = 0; mlti_cnt < num_mlti; mlti_cnt++) { | |
1606 if (mlti_cnt) { | |
1607 vido_size = stream_read_dword(demuxer->stream); // Size of the following vido chunk | |
1608 mp_msg(MSGT_DEMUX,MSGL_V,"VIDO size: %x\n", vido_size); | |
1609 vido_pos = stream_tell(demuxer->stream);; | |
1610 stream_skip(demuxer->stream, 4); | |
1611 tmp = stream_read_dword(demuxer->stream); | |
1612 } | |
1523 if(tmp != MKTAG('O', 'D', 'I', 'V')) | 1613 if(tmp != MKTAG('O', 'D', 'I', 'V')) |
1524 { | 1614 { |
1525 mp_msg(MSGT_DEMUX,MSGL_V,"Video: can't find VIDO in codec data\n"); | 1615 mp_msg(MSGT_DEMUX,MSGL_V,"Video: can't find VIDO in codec data\n"); |
1616 stream_skip(demuxer->stream, vido_size - 4); | |
1526 } else { | 1617 } else { |
1527 /* video header */ | 1618 /* video header */ |
1528 sh_video_t *sh = new_sh_video(demuxer, stream_id); | 1619 int vid = priv->is_mlti ? priv->streams_in_file + a_streams + v_streams : stream_id; |
1529 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "real", stream_id); | 1620 sh_video_t *sh = new_sh_video(demuxer, vid); |
1621 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "real", vid); | |
1622 priv->mp2rm_streamid[vid] = stream_id; | |
1623 priv->rm2mp[stream_id][mlti_cnt] = vid; | |
1624 mp_msg(MSGT_DEMUX,MSGL_V,"Mplayer vid %d is rm stream %d with MDPR index %d\n", vid, stream_id, mlti_cnt); | |
1530 | 1625 |
1531 sh->format = stream_read_dword_le(demuxer->stream); /* fourcc */ | 1626 sh->format = stream_read_dword_le(demuxer->stream); /* fourcc */ |
1532 mp_msg(MSGT_DEMUX,MSGL_V,"video fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format); | 1627 mp_msg(MSGT_DEMUX,MSGL_V,"video fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format); |
1533 | 1628 |
1534 /* emulate BITMAPINFOHEADER */ | 1629 /* emulate BITMAPINFOHEADER */ |
1567 } | 1662 } |
1568 stream_skip(demuxer->stream, 2); | 1663 stream_skip(demuxer->stream, 2); |
1569 | 1664 |
1570 { | 1665 { |
1571 // read and store codec extradata | 1666 // read and store codec extradata |
1572 unsigned int cnt = codec_data_size - (stream_tell(demuxer->stream) - codec_pos); | 1667 unsigned int cnt = vido_size - (stream_tell(demuxer->stream) - vido_pos); |
1573 if (cnt > 0x7fffffff - sizeof(*sh->bih)) { | 1668 if (cnt > 0x7fffffff - sizeof(*sh->bih)) { |
1574 mp_msg(MSGT_DEMUX, MSGL_ERR,"Extradata too big (%u)\n", cnt); | 1669 mp_msg(MSGT_DEMUX, MSGL_ERR,"Extradata too big (%u)\n", cnt); |
1575 } else { | 1670 } else { |
1576 sh->bih = realloc(sh->bih, sizeof(*sh->bih) + cnt); | 1671 sh->bih = realloc(sh->bih, sizeof(*sh->bih) + cnt); |
1577 sh->bih->biSize += cnt; | 1672 sh->bih->biSize += cnt; |
1594 demuxer->video->sh=sh; | 1689 demuxer->video->sh=sh; |
1595 } | 1690 } |
1596 | 1691 |
1597 ++v_streams; | 1692 ++v_streams; |
1598 | 1693 |
1599 } | 1694 } // VIDO |
1695 } // MLTI | |
1600 } else { | 1696 } else { |
1601 mp_msg(MSGT_DEMUX,MSGL_V,"Unknown video stream format\n"); | 1697 mp_msg(MSGT_DEMUX,MSGL_V,"Unknown video stream format\n"); |
1602 } | 1698 } |
1603 } else if (strstr(mimet,"logical-")) { | 1699 } else if (strstr(mimet,"logical-")) { |
1604 if (strstr(mimet,"fileinfo")) { | 1700 if (strstr(mimet,"fileinfo")) { |
1659 break; | 1755 break; |
1660 } | 1756 } |
1661 } | 1757 } |
1662 | 1758 |
1663 header_end: | 1759 header_end: |
1760 if(priv->is_multirate && priv->is_mlti) | |
1761 mp_msg(MSGT_DEMUX,MSGL_ERR,"Multirate and MLTI in the same file is bad. Please contact Mplayer developers.\n"); | |
1762 | |
1664 if(priv->is_multirate) { | 1763 if(priv->is_multirate) { |
1665 mp_msg(MSGT_DEMUX,MSGL_V,"Selected video id %d audio id %d\n", demuxer->video->id, demuxer->audio->id); | 1764 mp_msg(MSGT_DEMUX,MSGL_V,"Selected video id %d audio id %d\n", demuxer->video->id, demuxer->audio->id); |
1666 /* Perform some sanity checks to avoid checking streams id all over the code*/ | 1765 /* Perform some sanity checks to avoid checking streams id all over the code*/ |
1667 if (demuxer->audio->id >= MAX_STREAMS) { | 1766 if (demuxer->audio->id >= MAX_STREAMS) { |
1668 mp_msg(MSGT_DEMUX,MSGL_ERR,"Invalid audio stream %d. No sound will be played.\n", demuxer->audio->id); | 1767 mp_msg(MSGT_DEMUX,MSGL_ERR,"Invalid audio stream %d. No sound will be played.\n", demuxer->audio->id); |
1804 int next_offset = 0; | 1903 int next_offset = 0; |
1805 int64_t target_timestamp = 0; | 1904 int64_t target_timestamp = 0; |
1806 int streams = 0; | 1905 int streams = 0; |
1807 int retried = 0; | 1906 int retried = 0; |
1808 | 1907 |
1908 | |
1909 if (priv->is_mlti && (unsigned)vid < MAX_STREAMS) | |
1910 vid = priv->mp2rm_streamid[d_video->id]; | |
1911 if (priv->is_mlti && (unsigned)aid < MAX_STREAMS) | |
1912 aid = priv->mp2rm_streamid[d_audio->id]; | |
1809 | 1913 |
1810 if (sh_video && (unsigned)vid < MAX_STREAMS && priv->index_table_size[vid]) | 1914 if (sh_video && (unsigned)vid < MAX_STREAMS && priv->index_table_size[vid]) |
1811 streams |= 1; | 1915 streams |= 1; |
1812 if (sh_audio && (unsigned)aid < MAX_STREAMS && priv->index_table_size[aid]) | 1916 if (sh_audio && (unsigned)aid < MAX_STREAMS && priv->index_table_size[aid]) |
1813 streams |= 2; | 1917 streams |= 2; |