comparison mplayer.c @ 1375:dbcb5b5e1fae

file-format detection stuff moved out from mplayer.c to demuxer.c and dec_video.c
author arpi
date Sat, 21 Jul 2001 22:37:55 +0000
parents 7a2f1881b776
children 9e8781a3eefc
comparison
equal deleted inserted replaced
1374:2a4b2dd2fc0a 1375:dbcb5b5e1fae
139 #include "stream.h" 139 #include "stream.h"
140 #include "demuxer.h" 140 #include "demuxer.h"
141 141
142 #include "stheader.h" 142 #include "stheader.h"
143 143
144 static int avi_bitrate=0; 144 //static int avi_bitrate=0;
145
146 sh_audio_t* new_sh_audio(demuxer_t *demuxer,int id){
147 if(demuxer->a_streams[id]){
148 printf("Warning! Audio stream header %d redefined!\n",id);
149 } else {
150 printf("==> Found audio stream: %d\n",id);
151 demuxer->a_streams[id]=malloc(sizeof(sh_audio_t));
152 memset(demuxer->a_streams[id],0,sizeof(sh_audio_t));
153 }
154 return demuxer->a_streams[id];
155 }
156
157 sh_video_t* new_sh_video(demuxer_t *demuxer,int id){
158 if(demuxer->v_streams[id]){
159 printf("Warning! video stream header %d redefined!\n",id);
160 } else {
161 printf("==> Found video stream: %d\n",id);
162 demuxer->v_streams[id]=malloc(sizeof(sh_video_t));
163 memset(demuxer->v_streams[id],0,sizeof(sh_video_t));
164 }
165 return demuxer->v_streams[id];
166 }
167 145
168 char* encode_name=NULL; 146 char* encode_name=NULL;
169 char* encode_index_name=NULL; 147 char* encode_index_name=NULL;
170 int encode_bitrate=0; 148 int encode_bitrate=0;
171 149
180 demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id); 158 demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id);
181 159
182 int asf_check_header(demuxer_t *demuxer); 160 int asf_check_header(demuxer_t *demuxer);
183 int read_asf_header(demuxer_t *demuxer); 161 int read_asf_header(demuxer_t *demuxer);
184 162
163 demuxer_t* demux_open(stream_t *stream,int file_format);
164
185 // MPEG video stream parser: 165 // MPEG video stream parser:
186 #include "parse_es.c" 166 #include "parse_es.h"
187 167
188 extern int num_elementary_packets100; // for MPEG-ES fileformat detection 168 extern int num_elementary_packets100; // for MPEG-ES fileformat detection
189 extern int num_elementary_packets101; 169 extern int num_elementary_packets101;
190 extern int num_elementary_packetsPES; 170 extern int num_elementary_packetsPES;
191 171
192 extern picture_t *picture; // exported from libmpeg2/decode.c 172 extern picture_t *picture; // exported from libmpeg2/decode.c
193 173
194 static const int frameratecode2framerate[16] = { 174 int frameratecode2framerate[16] = {
195 0, 175 0,
196 // Official mpeg1/2 framerates: 176 // Official mpeg1/2 framerates:
197 24000*10000/1001, 24*10000,25*10000, 30000*10000/1001, 30*10000,50*10000,60000*10000/1001, 60*10000, 177 24000*10000/1001, 24*10000,25*10000, 30000*10000/1001, 30*10000,50*10000,60000*10000/1001, 60*10000,
198 // libmpeg3's "Unofficial economy rates": 178 // libmpeg3's "Unofficial economy rates":
199 1*10000,5*10000,10*10000,12*10000,15*10000,0,0 179 1*10000,5*10000,10*10000,12*10000,15*10000,0,0
681 661
682 //============ Open & Sync stream and detect file format =============== 662 //============ Open & Sync stream and detect file format ===============
683 663
684 if(!has_audio) audio_id=-2; // do NOT read audio packets... 664 if(!has_audio) audio_id=-2; // do NOT read audio packets...
685 665
686 //=============== Try to open as AVI file: ================= 666 demuxer=demux_open(stream,file_format);
687 if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_AVI){ 667 if(!demuxer) exit(1); // ERROR
688 stream_reset(stream); 668
689 demuxer=new_demuxer(stream,DEMUXER_TYPE_AVI,audio_id,video_id,dvdsub_id); 669 file_format=demuxer->file_format;
690 stream_seek(demuxer->stream,seek_to_byte); 670
691 { //---- RIFF header:
692 int id=stream_read_dword_le(demuxer->stream); // "RIFF"
693 if(id==mmioFOURCC('R','I','F','F')){
694 stream_read_dword_le(demuxer->stream); //filesize
695 id=stream_read_dword_le(demuxer->stream); // "AVI "
696 if(id==formtypeAVI){
697 printf("Detected AVI file format!\n");
698 file_format=DEMUXER_TYPE_AVI;
699 }
700 }
701 }
702 }
703 //=============== Try to open as ASF file: =================
704 if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_ASF){
705 stream_reset(stream);
706 demuxer=new_demuxer(stream,DEMUXER_TYPE_ASF,audio_id,video_id,dvdsub_id);
707 stream_seek(demuxer->stream,seek_to_byte);
708 if(asf_check_header(demuxer)){
709 printf("Detected ASF file format!\n");
710 file_format=DEMUXER_TYPE_ASF;
711 }
712 }
713 //=============== Try to open as MPEG-PS file: =================
714 if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MPEG_PS){
715 int pes=1;
716 while(pes>=0){
717 stream_reset(stream);
718 demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_PS,audio_id,video_id,dvdsub_id);
719 stream_seek(demuxer->stream,seek_to_byte);
720 if(!pes) demuxer->synced=1; // hack!
721 if(ds_fill_buffer(demuxer->video)){
722 if(!pes)
723 printf("Detected MPEG-PES file format!\n");
724 else
725 printf("Detected MPEG-PS file format!\n");
726 file_format=DEMUXER_TYPE_MPEG_PS;
727 } else {
728 // some hack to get meaningfull error messages to our unhappy users:
729 if(num_elementary_packets100>=2 && num_elementary_packets101>=2 &&
730 abs(num_elementary_packets101-num_elementary_packets100)<8){
731 if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4){
732 --pes;continue; // tricky...
733 }
734 file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :)
735 } else {
736 if(demuxer->synced==2)
737 printf("Missing MPEG video stream!? contact the author, it may be a bug :(\n");
738 else
739 printf("Not MPEG System Stream format... (maybe Transport Stream?)\n");
740 }
741 }
742 break;
743 }
744 }
745 //=============== Try to open as MPEG-ES file: =================
746 if(file_format==DEMUXER_TYPE_MPEG_ES){ // little hack, see above!
747 stream_reset(stream);
748 demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_ES,audio_id,video_id,dvdsub_id);
749 stream_seek(demuxer->stream,seek_to_byte);
750 if(!ds_fill_buffer(demuxer->video)){
751 printf("Invalid MPEG-ES stream??? contact the author, it may be a bug :(\n");
752 file_format=DEMUXER_TYPE_UNKNOWN;
753 } else {
754 printf("Detected MPEG-ES file format!\n");
755 }
756 }
757 #ifdef MOV
758 //=============== Try to open as MOV file: =================
759 if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MOV){
760 stream_reset(stream);
761 demuxer=new_demuxer(stream,DEMUXER_TYPE_MOV,audio_id,video_id,dvdsub_id);
762 // stream_seek(demuxer->stream,seek_to_byte);
763 if(mov_check_file(demuxer)){
764 printf("Detected QuickTime/MOV file format!\n");
765 file_format=DEMUXER_TYPE_MOV;
766 }
767 }
768 #endif
769 //=============== Unknown, exiting... ===========================
770 if(file_format==DEMUXER_TYPE_UNKNOWN){
771 fprintf(stderr,"============= Sorry, this file format not recognized/supported ===============\n");
772 fprintf(stderr,"=== If this file is an AVI, ASF or MPEG stream, please contact the author! ===\n");
773 GUI_MSG( mplUnknowFileType )
774 exit(1);
775 }
776 //====== File format recognized, set up these for compatibility: =========
777 d_audio=demuxer->audio; 671 d_audio=demuxer->audio;
778 d_video=demuxer->video; 672 d_video=demuxer->video;
779 d_dvdsub=demuxer->sub; 673 d_dvdsub=demuxer->sub;
780
781 sh_audio=NULL;
782 sh_video=NULL;
783
784 switch(file_format){
785 case DEMUXER_TYPE_AVI: {
786 //---- AVI header:
787 read_avi_header(demuxer,(stream->type!=STREAMTYPE_STREAM)?index_mode:-2);
788 stream_reset(demuxer->stream);
789 stream_seek(demuxer->stream,demuxer->movi_start);
790 demuxer->idx_pos=0;
791 demuxer->idx_pos_a=0;
792 demuxer->idx_pos_v=0;
793 if(demuxer->idx_size>0){
794 // decide index format:
795 if(((AVIINDEXENTRY *)demuxer->idx)[0].dwChunkOffset<demuxer->movi_start)
796 demuxer->idx_offset=demuxer->movi_start-4;
797 else
798 demuxer->idx_offset=0;
799 if(verbose) printf("AVI index offset: %d\n",demuxer->idx_offset);
800 }
801 // demuxer->endpos=avi_header.movi_end;
802
803 if(demuxer->idx_size>0){
804 // check that file is non-interleaved:
805 int i;
806 int a_pos=-1;
807 int v_pos=-1;
808 for(i=0;i<demuxer->idx_size;i++){
809 AVIINDEXENTRY* idx=&((AVIINDEXENTRY *)demuxer->idx)[i];
810 demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);
811 int pos=idx->dwChunkOffset+demuxer->idx_offset;
812 if(a_pos==-1 && ds==demuxer->audio){
813 a_pos=pos;
814 if(v_pos!=-1) break;
815 }
816 if(v_pos==-1 && ds==demuxer->video){
817 v_pos=pos;
818 if(a_pos!=-1) break;
819 }
820 }
821 if(v_pos==-1){
822 fprintf(stderr,"AVI_NI: missing video stream!? contact the author, it may be a bug :(\n");
823 GUI_MSG( mplErrorAVINI )
824 exit(1);
825 }
826 if(a_pos==-1){
827 printf("AVI_NI: No audio stream found -> nosound\n");
828 has_audio=0;sh_audio=NULL;
829 } else {
830 if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB
831 printf("%s NON-INTERLEAVED AVI file-format!\n",force_ni?"Forced":"Detected");
832 demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!!
833 pts_from_bps=1; // force BPS sync!
834 }
835 }
836 } else {
837 // no index
838 if(force_ni){
839 printf("Using NON-INTERLEAVED Broken AVI file-format!\n");
840 demuxer->type=DEMUXER_TYPE_AVI_NINI; // HACK!!!!
841 demuxer->idx_pos_a=
842 demuxer->idx_pos_v=demuxer->movi_start;
843 pts_from_bps=1; // force BPS sync!
844 }
845 }
846 if(!ds_fill_buffer(d_video)){
847 fprintf(stderr,"AVI: missing video stream!? contact the author, it may be a bug :(\n");
848 GUI_MSG( mplAVIErrorMissingVideoStream )
849 exit(1);
850 }
851 sh_video=d_video->sh;sh_video->ds=d_video;
852 if(has_audio){
853 if(verbose) printf("AVI: Searching for audio stream (id:%d)\n",d_audio->id);
854 if(!ds_fill_buffer(d_audio)){
855 printf("AVI: No Audio stream found... ->nosound\n");
856 has_audio=0;sh_audio=NULL;
857 } else {
858 sh_audio=d_audio->sh;sh_audio->ds=d_audio;
859 sh_audio->format=sh_audio->wf->wFormatTag;
860 }
861 }
862 // calc. FPS:
863 sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
864 sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
865 // calculating video bitrate:
866 avi_bitrate=demuxer->movi_end-demuxer->movi_start-demuxer->idx_size*8;
867 if(sh_audio) avi_bitrate-=sh_audio->audio.dwLength;
868 if(verbose) printf("AVI video length=%d\n",avi_bitrate);
869 avi_bitrate=((float)avi_bitrate/(float)sh_video->video.dwLength)*sh_video->fps;
870 printf("VIDEO: [%.4s] %ldx%ld %dbpp %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n",
871 (char *)&sh_video->bih->biCompression,
872 sh_video->bih->biWidth,
873 sh_video->bih->biHeight,
874 sh_video->bih->biBitCount,
875 sh_video->fps,
876 avi_bitrate*0.008f,
877 avi_bitrate/1024.0f );
878 break;
879 }
880 case DEMUXER_TYPE_ASF: {
881 //---- ASF header:
882 read_asf_header(demuxer);
883 stream_reset(demuxer->stream);
884 stream_seek(demuxer->stream,demuxer->movi_start);
885 demuxer->idx_pos=0;
886 // demuxer->endpos=avi_header.movi_end;
887 if(!ds_fill_buffer(d_video)){
888 printf("ASF: no video stream found!\n");
889 sh_video=NULL;
890 //printf("ASF: missing video stream!? contact the author, it may be a bug :(\n");
891 //GUI_MSG( mplASFErrorMissingVideoStream )
892 //exit(1);
893 } else {
894 sh_video=d_video->sh;sh_video->ds=d_video;
895 sh_video->fps=1000.0f; sh_video->frametime=0.001f; // 1ms
896 printf("VIDEO: [%.4s] %ldx%ld %dbpp\n",
897 (char *)&sh_video->bih->biCompression,
898 sh_video->bih->biWidth,
899 sh_video->bih->biHeight,
900 sh_video->bih->biBitCount);
901 }
902 if(has_audio){
903 if(verbose) printf("ASF: Searching for audio stream (id:%d)\n",d_audio->id);
904 if(!ds_fill_buffer(d_audio)){
905 printf("ASF: No Audio stream found... ->nosound\n");
906 has_audio=0;sh_audio=NULL;
907 } else {
908 sh_audio=d_audio->sh;sh_audio->ds=d_audio;
909 sh_audio->format=sh_audio->wf->wFormatTag;
910 }
911 }
912 break;
913 }
914 case DEMUXER_TYPE_MPEG_ES: {
915 has_audio=0;sh_audio=NULL; // ES streams has no audio channel
916 d_video->sh=new_sh_video(demuxer,0); // create dummy video stream header, id=0
917 break;
918 }
919 case DEMUXER_TYPE_MPEG_PS: {
920 if(has_audio) {
921 if(!ds_fill_buffer(d_audio)){
922 printf("MPEG: No Audio stream found... ->nosound\n");
923 has_audio=0;sh_audio=NULL;
924 } else {
925 sh_audio=d_audio->sh;sh_audio->ds=d_audio;
926 switch(d_audio->id & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id)
927 case 0x00: sh_audio->format=0x50;break; // mpeg
928 case 0xA0: sh_audio->format=0x10001;break; // dvd pcm
929 case 0x80: sh_audio->format=0x2000;break; // ac3
930 default: has_audio=0;sh_audio=NULL; // unknown type
931 }
932 }
933 }
934 break;
935 }
936 } // switch(file_format)
937 674
938 // DUMP STREAMS: 675 // DUMP STREAMS:
939 if(stream_dump_type){ 676 if(stream_dump_type){
940 FILE *f; 677 FILE *f;
941 demux_stream_t *ds=NULL; 678 demux_stream_t *ds=NULL;
966 fclose(f); 703 fclose(f);
967 printf("core dumped :)\n"); 704 printf("core dumped :)\n");
968 exit(1); 705 exit(1);
969 } 706 }
970 707
971 708 sh_audio=d_audio->sh;
972 // Determine image properties: 709 sh_video=d_video->sh;
973 switch(file_format){ 710
974 case DEMUXER_TYPE_AVI: 711 if(sh_video){
975 case DEMUXER_TYPE_ASF: { 712
976 // display info: 713 if(!video_read_properties(sh_video)) exit(1); // couldn't read header?
977 if(sh_video){ 714
978 sh_video->format=sh_video->bih->biCompression; 715 printf("[V] filefmt:%d fourcc:0x%X size:%dx%d fps:%5.2f ftime:=%6.4f\n",
979 sh_video->disp_w=sh_video->bih->biWidth;
980 sh_video->disp_h=abs(sh_video->bih->biHeight);
981 }
982 break;
983 }
984 case DEMUXER_TYPE_MPEG_ES:
985 case DEMUXER_TYPE_MPEG_PS: {
986 // Find sequence_header first:
987 if(verbose) printf("Searching for sequence header... ");fflush(stdout);
988 while(1){
989 int i=sync_video_packet(d_video);
990 if(i==0x1B3) break; // found it!
991 if(!i || !skip_video_packet(d_video)){
992 if(verbose) printf("NONE :(\n");
993 fprintf(stderr,"MPEG: FATAL: EOF while searching for sequence header\n");
994 GUI_MSG( mplMPEGErrorSeqHeaderSearch )
995 exit(1);
996 }
997 }
998 if(verbose) printf("OK!\n");
999 sh_video=d_video->sh;sh_video->ds=d_video;
1000 sh_video->format=0x10000001; // mpeg video
1001 mpeg2_init();
1002 // ========= Read & process sequence header & extension ============
1003 videobuffer=shmem_alloc(VIDEOBUFFER_SIZE);
1004 if(!videobuffer){
1005 fprintf(stderr,"Cannot allocate shared memory\n");
1006 GUI_MSG( mplErrorShMemAlloc )
1007 exit(0);
1008 }
1009 videobuf_len=0;
1010 if(!read_video_packet(d_video)){
1011 fprintf(stderr,"FATAL: Cannot read sequence header!\n");
1012 GUI_MSG( mplMPEGErrorCannotReadSeqHeader )
1013 exit(1);
1014 }
1015 if(header_process_sequence_header (picture, &videobuffer[4])) {
1016 printf ("bad sequence header!\n");
1017 GUI_MSG( mplMPEGErrorBadSeqHeader )
1018 exit(1);
1019 }
1020 if(sync_video_packet(d_video)==0x1B5){ // next packet is seq. ext.
1021 videobuf_len=0;
1022 if(!read_video_packet(d_video)){
1023 fprintf(stderr,"FATAL: Cannot read sequence header extension!\n");
1024 GUI_MSG( mplMPEGErrorCannotReadSeqHeaderExt )
1025 exit(1);
1026 }
1027 if(header_process_extension (picture, &videobuffer[4])) {
1028 printf ("bad sequence header extension!\n");
1029 GUI_MSG( mplMPEGErrorBadSeqHeaderExt )
1030 exit(1);
1031 }
1032 }
1033 // display info:
1034 sh_video->fps=frameratecode2framerate[picture->frame_rate_code]*0.0001f;
1035 if(!sh_video->fps){
1036 if(!force_fps){
1037 fprintf(stderr,"FPS not specified (or invalid) in the header! Use the -fps option!\n");
1038 exit(1);
1039 }
1040 sh_video->frametime=0;
1041 } else {
1042 sh_video->frametime=10000.0f/(float)frameratecode2framerate[picture->frame_rate_code];
1043 }
1044 sh_video->disp_w=picture->display_picture_width;
1045 sh_video->disp_h=picture->display_picture_height;
1046 // info:
1047 if(verbose) printf("mpeg bitrate: %d (%X)\n",picture->bitrate,picture->bitrate);
1048 printf("VIDEO: %s %dx%d (aspect %d) %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n",
1049 picture->mpeg1?"MPEG1":"MPEG2",
1050 sh_video->disp_w,sh_video->disp_h,
1051 picture->aspect_ratio_information,
1052 sh_video->fps,
1053 picture->bitrate*0.5f,
1054 picture->bitrate/16.0f );
1055 break;
1056 }
1057 } // switch(file_format)
1058
1059
1060 if(sh_video)
1061 printf("[V] filefmt:%d fourcc:0x%X size:%dx%d fps:%5.2f ftime:=%6.4f\n",
1062 file_format,sh_video->format, sh_video->disp_w,sh_video->disp_h, 716 file_format,sh_video->format, sh_video->disp_w,sh_video->disp_h,
1063 sh_video->fps,sh_video->frametime 717 sh_video->fps,sh_video->frametime
1064 ); 718 );
719
720 if(!sh_video->fps && !force_fps){
721 fprintf(stderr,"FPS not specified (or invalid) in the header! Use the -fps option!\n");
722 exit(1);
723 }
724
725 }
1065 726
1066 fflush(stdout); 727 fflush(stdout);
1067 728
1068 if(!sh_video){ 729 if(!sh_video){
1069 fprintf(stderr,"Sorry, no video stream... it's unplayable yet\n"); 730 fprintf(stderr,"Sorry, no video stream... it's unplayable yet\n");
1288 float c_total=0; 949 float c_total=0;
1289 float max_pts_correction=0;//default_max_pts_correction; 950 float max_pts_correction=0;//default_max_pts_correction;
1290 int eof=0; 951 int eof=0;
1291 int force_redraw=0; 952 int force_redraw=0;
1292 float num_frames=0; // number of frames played 953 float num_frames=0; // number of frames played
1293 int grab_frames=0; 954 int grab_frames=1;
1294 char osd_text_buffer[64]; 955 char osd_text_buffer[64];
1295 int drop_frame=0; 956 int drop_frame=0;
1296 int drop_frame_cnt=0; 957 int drop_frame_cnt=0;
1297 958
1298 #ifdef HAVE_LIRC 959 #ifdef HAVE_LIRC