From 422b0d2a4c936d87ed27ee7b56e21d2d60752194 Mon Sep 17 00:00:00 2001 From: arpi Date: Sat, 16 Nov 2002 03:42:14 +0000 Subject: demuxer_control(), percent position and time length query implemented in asf, avi, mpeg demuxers. patch by Balatoni Denes git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8209 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libmpdemux/asfheader.c | 4 ++++ libmpdemux/aviheader.h | 1 + libmpdemux/demux_asf.c | 27 +++++++++++++++++++++++-- libmpdemux/demux_avi.c | 53 +++++++++++++++++++++++++++++++++++++++----------- libmpdemux/demux_mpg.c | 23 +++++++++++++++++++++- libmpdemux/demuxer.c | 38 ++++++++++++++++++++++++++++++++++++ libmpdemux/demuxer.h | 12 ++++++++++++ mplayer.c | 1 + 8 files changed, 145 insertions(+), 14 deletions(-) diff --git a/libmpdemux/asfheader.c b/libmpdemux/asfheader.c index bab9928072..ea77f798e6 100644 --- a/libmpdemux/asfheader.c +++ b/libmpdemux/asfheader.c @@ -48,6 +48,8 @@ int asf_scrambling_h=1; int asf_scrambling_w=1; int asf_scrambling_b=1; int asf_packetsize=0; +double asf_packetrate=0; +int asf_movielength=0; //int i; @@ -214,6 +216,8 @@ while(!stream_eof(demuxer->stream)){ mp_msg(MSGT_HEADER,MSGL_V,"ASF: packets: %d flags: %d max_packet_size: %d min_packet_size: %d max_bitrate: %d preroll: %d\n",(int)fileh.num_packets,(int)fileh.flags,(int)fileh.min_packet_size,(int)fileh.max_packet_size,(int)fileh.max_bitrate,(int)fileh.preroll); asf_packetsize=fileh.max_packet_size; asf_packet=malloc(asf_packetsize); // !!! + asf_packetrate=fileh.max_bitrate/8.0/(double)asf_packetsize; + asf_movielength=fileh.send_duration/10000000LL; break; case ASF_GUID_PREFIX_data_chunk: // guid_data_chunk demuxer->movi_start=stream_tell(demuxer->stream)+26; diff --git a/libmpdemux/aviheader.h b/libmpdemux/aviheader.h index fce379c596..4ca63fc9c0 100644 --- a/libmpdemux/aviheader.h +++ b/libmpdemux/aviheader.h @@ -106,6 +106,7 @@ typedef struct { unsigned int pts_corr_bytes; unsigned char pts_corrected; unsigned char pts_has_video; + unsigned int numberofframes; } avi_priv_t; #define AVI_PRIV ((avi_priv_t*)(demuxer->priv)) diff --git a/libmpdemux/demux_asf.c b/libmpdemux/demux_asf.c index 37011bd8fd..9d6196dab5 100644 --- a/libmpdemux/demux_asf.c +++ b/libmpdemux/demux_asf.c @@ -35,7 +35,8 @@ extern int asf_scrambling_h; extern int asf_scrambling_w; extern int asf_scrambling_b; extern int asf_packetsize; - +extern double asf_packetrate; +extern int asf_movielength; // based on asf file-format doc by Eugene [http://divx.euro.ru] @@ -357,7 +358,7 @@ void demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,int flags){ //FIXME: reports good or bad to steve@daviesfam.org please //================= seek in ASF ========================== - float p_rate=10; // packets / sec + float p_rate=asf_packetrate; // packets / sec off_t rel_seek_packs=(flags&2)? // FIXME: int may be enough? (rel_seek_secs*(demuxer->movi_end-demuxer->movi_start)/asf_packetsize): (rel_seek_secs*p_rate); @@ -395,3 +396,25 @@ void demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,int flags){ } +int demux_asf_control(demuxer_t *demuxer,int cmd, void *arg){ + demux_stream_t *d_audio=demuxer->audio; + demux_stream_t *d_video=demuxer->video; + sh_audio_t *sh_audio=d_audio->sh; + sh_video_t *sh_video=d_video->sh; + + switch(cmd) { + case DEMUXER_CTRL_GET_TIME_LENGTH: + *((unsigned long *)arg)=(unsigned long)(asf_movielength); + return DEMUXER_CTRL_OK; + + case DEMUXER_CTRL_GET_PERCENT_POS: + if (demuxer->movi_end==demuxer->movi_start) { + return DEMUXER_CTRL_DONTKNOW; + } + *((int *)arg)=(int)((demuxer->filepos-demuxer->movi_start)/((demuxer->movi_end-demuxer->movi_start)/100)); + return DEMUXER_CTRL_OK; + + default: + return DEMUXER_CTRL_NOTIMPL; + } +} diff --git a/libmpdemux/demux_avi.c b/libmpdemux/demux_avi.c index 2394179b51..8406e8f794 100644 --- a/libmpdemux/demux_avi.c +++ b/libmpdemux/demux_avi.c @@ -552,6 +552,15 @@ demuxer_t* demux_open_avi(demuxer_t* demuxer){ if(sh_audio) sh_video->i_bps-=sh_audio->audio.dwLength; mp_msg(MSGT_DEMUX,MSGL_V,"AVI video length=%lu\n",(unsigned long)sh_video->i_bps); sh_video->i_bps=((float)sh_video->i_bps/(float)sh_video->video.dwLength)*sh_video->fps; + + if((priv->numberofframes=sh_video->video.dwLength)<=1) + // bad video header, try to get number of frames from audio + if(sh_audio && sh_audio->wf->nAvgBytesPerSec) priv->numberofframes=sh_video->fps*sh_audio->audio.dwLength/sh_audio->wf->nAvgBytesPerSec; + if(priv->numberofframes<=1){ + mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CouldntDetFNo); + priv->numberofframes=0; + } + mp_msg(MSGT_DEMUX,MSGL_INFO,"VIDEO: [%.4s] %ldx%ld %dbpp %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n", (char *)&sh_video->bih->biCompression, sh_video->bih->biWidth, @@ -588,17 +597,7 @@ void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){ } if(flags&2){ - // float 0..1 - int total=sh_video->video.dwLength; - if(total<=1){ - // bad video header, try to get it from audio - if(sh_audio) total=sh_video->fps*sh_audio->audio.dwLength/sh_audio->wf->nAvgBytesPerSec; - if(total<=1){ - mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CouldntDetFNo); - total=0; - } - } - rel_seek_frames=rel_seek_secs*total; + rel_seek_frames=rel_seek_secs*priv->numberofframes; } priv->skip_video_frames=0; @@ -785,3 +784,35 @@ void demux_close_avi(demuxer_t *demuxer) { free(priv->idx); free(priv); } + + +int demux_avi_control(demuxer_t *demuxer,int cmd, void *arg){ + avi_priv_t *priv=demuxer->priv; + demux_stream_t *d_audio=demuxer->audio; + demux_stream_t *d_video=demuxer->video; + sh_audio_t *sh_audio=d_audio->sh; + sh_video_t *sh_video=d_video->sh; + + + + switch(cmd) { + case DEMUXER_CTRL_GET_TIME_LENGTH: + if (!priv->numberofframes) return DEMUXER_CTRL_DONTKNOW; + *((unsigned long *)arg)=priv->numberofframes/sh_video->fps; + if (sh_video->video.dwLength<=1) return DEMUXER_CTRL_GUESS; + return DEMUXER_CTRL_OK; + + case DEMUXER_CTRL_GET_PERCENT_POS: + if (!priv->numberofframes) { + if (demuxer->movi_end==demuxer->movi_start) return DEMUXER_CTRL_DONTKNOW; + *((int *)arg)=(int)((demuxer->filepos-demuxer->movi_start)/((demuxer->movi_end-demuxer->movi_start)/100)); + return DEMUXER_CTRL_OK; + } + *((int *)arg)=(int)(priv->video_pack_no*100/priv->numberofframes); + if (sh_video->video.dwLength<=1) return DEMUXER_CTRL_GUESS; + return DEMUXER_CTRL_OK; + + default: + return DEMUXER_CTRL_NOTIMPL; + } +} diff --git a/libmpdemux/demux_mpg.c b/libmpdemux/demux_mpg.c index 5437d8a0e5..bdc28fd618 100644 --- a/libmpdemux/demux_mpg.c +++ b/libmpdemux/demux_mpg.c @@ -403,7 +403,28 @@ void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,int flags){ if(i==0x1B3 || i==0x1B8) break; // found it! if(!i || !skip_video_packet(d_video)) break; // EOF? } +} +int demux_mpg_control(demuxer_t *demuxer,int cmd, void *arg){ + demux_stream_t *d_audio=demuxer->audio; + demux_stream_t *d_video=demuxer->video; + sh_audio_t *sh_audio=d_audio->sh; + sh_video_t *sh_video=d_video->sh; + switch(cmd) { + case DEMUXER_CTRL_GET_TIME_LENGTH: + if(!sh_video->i_bps) // unspecified or VBR + return DEMUXER_CTRL_DONTKNOW; + *((unsigned long *)arg)=(demuxer->movi_end-demuxer->movi_start)/sh_video->i_bps; + return DEMUXER_CTRL_GUESS; + + case DEMUXER_CTRL_GET_PERCENT_POS: + if (demuxer->movi_end==demuxer->movi_start) + return DEMUXER_CTRL_DONTKNOW; + *((int *)arg)=(int)((demuxer->filepos-demuxer->movi_start)/((demuxer->movi_end-demuxer->movi_start)/100)); + return DEMUXER_CTRL_OK; + + default: + return DEMUXER_CTRL_NOTIMPL; + } } - diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index 29a6d54e0d..67dca84f77 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -1245,3 +1245,41 @@ char* demux_info_get(demuxer_t *demuxer, char *opt) { return NULL; } +extern int demux_mpg_control(demuxer_t *demuxer, int cmd, void *arg); +extern int demux_asf_control(demuxer_t *demuxer, int cmd, void *arg); +extern int demux_avi_control(demuxer_t *demuxer, int cmd, void *arg); + +int demux_control(demuxer_t *demuxer, int cmd, void *arg) { + switch(demuxer->type) { + case DEMUXER_TYPE_MPEG_ES: + case DEMUXER_TYPE_MPEG_PS: + return demux_mpg_control(demuxer,cmd,arg); + case DEMUXER_TYPE_ASF: + return demux_asf_control(demuxer,cmd,arg); + case DEMUXER_TYPE_AVI: + return demux_avi_control(demuxer,cmd,arg); + + default: + return DEMUXER_CTRL_NOTIMPL; + } +} + + + +unsigned long demuxer_get_time_length(demuxer_t *demuxer){ + unsigned long get_time_ans; + if (demux_control(demuxer, DEMUXER_CTRL_GET_TIME_LENGTH,(void *)&get_time_ans)<=0) { + get_time_ans=0; + } + return get_time_ans; +} + +int demuxer_get_percent_pos(demuxer_t *demuxer){ + int ans; + if (demux_control(demuxer, DEMUXER_CTRL_GET_PERCENT_POS, &ans)<=DEMUXER_CTRL_OK) { + ans=0; + } + if (ans>100 || ans<0) ans=0; + return ans; +} + diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index fd25e2c933..699843c7bb 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -50,6 +50,14 @@ #define DEMUXER_TIME_BPS 3 +// DEMUXER control commands/answers +#define DEMUXER_CTRL_NOTIMPL -1 +#define DEMUXER_CTRL_DONTKNOW 0 +#define DEMUXER_CTRL_OK 1 +#define DEMUXER_CTRL_GUESS 2 +#define DEMUXER_CTRL_GET_TIME_LENGTH 10 +#define DEMUXER_CTRL_GET_PERCENT_POS 11 + // Holds one packet/frame/whatever typedef struct demux_packet_st { int len; @@ -234,5 +242,9 @@ extern int pts_from_bps; int demux_info_add(demuxer_t *demuxer, char *opt, char *param); char* demux_info_get(demuxer_t *demuxer, char *opt); int demux_info_print(demuxer_t *demuxer); +int demux_control(demuxer_t *demuxer, int cmd, void *arg); #endif + +extern unsigned long demuxer_get_time_length(demuxer_t *demuxer); +extern int demuxer_get_percent_pos(demuxer_t *demuxer); diff --git a/mplayer.c b/mplayer.c index e6fd4585bc..1f2a92419c 100644 --- a/mplayer.c +++ b/mplayer.c @@ -1239,6 +1239,7 @@ if(identify) { mp_msg(MSGT_GLOBAL,MSGL_INFO,"ID_AUDIO_RATE=%d\n", sh_audio->samplerate); mp_msg(MSGT_GLOBAL,MSGL_INFO,"ID_AUDIO_NCH=%d\n", sh_audio->channels); } + mp_msg(MSGT_GLOBAL,MSGL_INFO,"ID_LENGTH=%ld\n", demuxer_get_time_length(demuxer)); goto goto_next_file; } -- cgit v1.2.3