demuxer.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,287 行 · 第 1/3 页
C
1,287 行
return NULL;//====== File format recognized, set up these for compatibility: =========dmx_open:demuxer->file_format=file_format;if ((sh_video=demuxer->video->sh) && sh_video->bih){int biComp=le2me_32(sh_video->bih->biCompression); mp_msg(MSGT_DEMUX,MSGL_INFO,"VIDEO: [%.4s] %dx%d %dbpp %5.3f fps %5.1f kbps (%4.1f kbyte/s)\n", (char *)&biComp, sh_video->bih->biWidth, sh_video->bih->biHeight, sh_video->bih->biBitCount, sh_video->fps, sh_video->i_bps*0.008f, sh_video->i_bps/1024.0f );}return demuxer;}char* audio_stream = NULL;char* sub_stream = NULL;int demuxer_type = 0; // used by rawaudio and rawvideoint audio_stream_cache = 0;char *demuxer_name = NULL; // parameter from -demuxerchar *audio_demuxer_name = NULL; // parameter from -audio-demuxerchar *sub_demuxer_name = NULL; // parameter from -sub-demuxerextern int hr_mp3_seek;extern float stream_cache_min_percent;extern float stream_cache_seek_min_percent;demuxer_t* demux_open(stream_t *vs,int file_format,int audio_id,int video_id,int dvdsub_id,char* filename){ stream_t *as = NULL,*ss = NULL; demuxer_t *vd,*ad = NULL,*sd = NULL; int afmt =DEMUXER_TYPE_UNKNOWN,sfmt = DEMUXER_TYPE_UNKNOWN ; int audio_demuxer_type = 0, sub_demuxer_type = 0; int demuxer_force = 0, audio_demuxer_force = 0, sub_demuxer_force = 0; //F("1\n"); if ((demuxer_type = get_demuxer_type_from_name(demuxer_name, &demuxer_force)) < 0) { mp_msg(MSGT_DEMUXER,MSGL_ERR,"-demuxer %s does not exist.\n",demuxer_name); } //F("2\n"); if ((audio_demuxer_type = get_demuxer_type_from_name(audio_demuxer_name, &audio_demuxer_force)) < 0) { mp_msg(MSGT_DEMUXER,MSGL_ERR,"-audio-demuxer %s does not exist.\n",audio_demuxer_name); } //F("3\n"); if ((sub_demuxer_type = get_demuxer_type_from_name(sub_demuxer_name, &sub_demuxer_force)) < 0) { mp_msg(MSGT_DEMUXER,MSGL_ERR,"-sub-demuxer %s does not exist.\n",sub_demuxer_name); } //F("4\n"); if(audio_stream) { as = open_stream(audio_stream,0,&afmt); if(!as) { mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_CannotOpenAudioStream,audio_stream); return NULL; } if(audio_stream_cache) { if(!stream_enable_cache(as,audio_stream_cache*1024,audio_stream_cache*1024*(stream_cache_min_percent / 100.0), audio_stream_cache*1024*(stream_cache_seek_min_percent / 100.0))) { free_stream(as); mp_msg(MSGT_DEMUXER,MSGL_ERR,"Can't enable audio stream cache\n"); return NULL; } } } //F("5\n"); if(sub_stream) { ss = open_stream(sub_stream,0,&sfmt); if(!ss) { mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_CannotOpenSubtitlesStream,sub_stream); return NULL; } } //F("6\n"); vd = demux_open_stream(vs, demuxer_type ? demuxer_type : file_format, demuxer_force, audio_stream ? -2 : audio_id, video_id, sub_stream ? -2 : dvdsub_id, filename); //F("7\n"); if(!vd) { if(as) free_stream(as); if(ss) free_stream(ss); return NULL; } //F("8\n"); if(as) { ad = demux_open_stream(as, audio_demuxer_type ? audio_demuxer_type : afmt, audio_demuxer_force, audio_id, -2, -2, audio_stream); if(!ad) { mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_OpeningAudioDemuxerFailed,audio_stream); free_stream(as); } else if(ad->audio->sh && ((sh_audio_t*)ad->audio->sh)->format == 0x55) // MP3 hr_mp3_seek=1; // Enable high res seeking } //F("9\n"); if(ss) { sd = demux_open_stream(ss, sub_demuxer_type ? sub_demuxer_type : sfmt, sub_demuxer_force, -2, -2, dvdsub_id, sub_stream); if(!sd) { mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_OpeningSubtitlesDemuxerFailed,sub_stream); free_stream(ss); } } //F("10\n"); if(ad && sd) return new_demuxers_demuxer(vd,ad,sd); else if(ad) return new_demuxers_demuxer(vd,ad,vd); else if(sd) return new_demuxers_demuxer(vd,vd,sd); else return vd;}int demux_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){ 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; double tmp = 0; double pts;if(!demuxer->seekable){ if(demuxer->file_format==DEMUXER_TYPE_AVI) mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CantSeekRawAVI);#ifdef USE_TV else if (demuxer->file_format==DEMUXER_TYPE_TV) mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_TVInputNotSeekable);#endif else mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CantSeekFile); return 0;} // clear demux buffers: if(sh_audio){ ds_free_packs(d_audio);sh_audio->a_buffer_len=0;} ds_free_packs(d_video); ds_free_packs(demuxer->sub); demuxer->stream->eof=0; // clear eof flag demuxer->video->eof=0; demuxer->audio->eof=0;#if 0 if(sh_audio) sh_audio->timer=sh_video->timer;#else if(sh_video) sh_video->timer=0; // !!!!!!#endif if(flags & 1) // absolute seek pts = 0.0f; else { if(demuxer->stream_pts == MP_NOPTS_VALUE) goto dmx_seek; pts = demuxer->stream_pts; } if(flags & 2) { // percent seek if(stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, &tmp) == STREAM_UNSUPPORTED) goto dmx_seek; pts += tmp * rel_seek_secs; } else pts += rel_seek_secs; if(stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_TIME, &pts) != STREAM_UNSUPPORTED) { demux_control(demuxer, DEMUXER_CTRL_RESYNC, NULL); return 1; }dmx_seek:if (demuxer->desc->seek) demuxer->desc->seek(demuxer,rel_seek_secs,audio_delay,flags); if (sh_audio) resync_audio_stream(sh_audio);return 1;}int demux_info_add(demuxer_t *demuxer, const char *opt, const char *param){ char **info = demuxer->info; int n = 0; for(n = 0; info && info[2*n] != NULL; n++) { if(!strcasecmp(opt,info[2*n])) { mp_msg(MSGT_DEMUX, MSGL_INFO,MSGTR_DemuxerInfoChanged,opt,param); free(info[2*n+1]); info[2*n+1] = strdup(param); return 0; } } info = demuxer->info = (char**)realloc(info,(2*(n+2))*sizeof(char*)); info[2*n] = strdup(opt); info[2*n+1] = strdup(param); memset(&info[2*(n+1)],0,2*sizeof(char*)); return 1;}int demux_info_print(demuxer_t *demuxer){ char **info = demuxer->info; int n; if(!info) return 0; mp_msg(MSGT_DEMUX, MSGL_INFO,MSGTR_ClipInfo); for(n = 0; info[2*n] != NULL ; n++) { mp_msg(MSGT_DEMUX, MSGL_INFO, " %s: %s\n",info[2*n],info[2*n+1]); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CLIP_INFO_NAME%d=%s\n", n, info[2*n]); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CLIP_INFO_VALUE%d=%s\n", n, info[2*n+1]); } mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CLIP_INFO_N=%d\n", n); return 0;}char* demux_info_get(demuxer_t *demuxer, const char *opt) { int i; char **info = demuxer->info; for(i = 0; info && info[2*i] != NULL; i++) { if(!strcasecmp(opt,info[2*i])) return info[2*i+1]; } return NULL;}int demux_control(demuxer_t *demuxer, int cmd, void *arg) { if (demuxer->desc->control) return demuxer->desc->control(demuxer,cmd,arg); return DEMUXER_CTRL_NOTIMPL;}double demuxer_get_time_length(demuxer_t *demuxer){ double get_time_ans; sh_video_t *sh_video = demuxer->video->sh; sh_audio_t *sh_audio = demuxer->audio->sh; // <= 0 means DEMUXER_CTRL_NOTIMPL or DEMUXER_CTRL_DONTKNOW if (demux_control(demuxer, DEMUXER_CTRL_GET_TIME_LENGTH,(void *)&get_time_ans)<=0) { if (sh_video && sh_video->i_bps && sh_audio && sh_audio->i_bps) get_time_ans = (double)(demuxer->movi_end-demuxer->movi_start)/(sh_video->i_bps+sh_audio->i_bps); else if (sh_video && sh_video->i_bps) get_time_ans = (double)(demuxer->movi_end-demuxer->movi_start)/sh_video->i_bps; else if (sh_audio && sh_audio->i_bps) get_time_ans = (double)(demuxer->movi_end-demuxer->movi_start)/sh_audio->i_bps; else get_time_ans=0; } return get_time_ans;}/** * \brief demuxer_get_current_time() returns the time of the current play in three possible ways: * either when the stream reader satisfies STREAM_CTRL_GET_CURRENT_TIME (e.g. dvd) * or using sh_video->pts when the former method fails * 0 otherwise * \return the current play time */int demuxer_get_current_time(demuxer_t *demuxer){ double get_time_ans = 0; sh_video_t *sh_video = demuxer->video->sh; if(demuxer->stream_pts != MP_NOPTS_VALUE) get_time_ans = demuxer->stream_pts; else if(sh_video) get_time_ans = sh_video->pts; return (int) get_time_ans;}int demuxer_get_percent_pos(demuxer_t *demuxer){ int ans = 0; int res = demux_control(demuxer, DEMUXER_CTRL_GET_PERCENT_POS, &ans); int len = (demuxer->movi_end - demuxer->movi_start) / 100; if (res <= 0) { if (len > 0) ans = (demuxer->filepos - demuxer->movi_start) / len; else ans = 0; } if (ans < 0) ans = 0; if (ans > 100) ans = 100; return ans;}int demuxer_switch_audio(demuxer_t *demuxer, int index){ int res = demux_control(demuxer, DEMUXER_CTRL_SWITCH_AUDIO, &index); if (res == DEMUXER_CTRL_NOTIMPL) index = demuxer->audio->id; return index;}int demuxer_switch_video(demuxer_t *demuxer, int index){ int res = demux_control(demuxer, DEMUXER_CTRL_SWITCH_VIDEO, &index); if (res == DEMUXER_CTRL_NOTIMPL) index = demuxer->video->id; return index;}int demuxer_add_chapter(demuxer_t* demuxer, const char* name, uint64_t start, uint64_t end){ if (demuxer->chapters == NULL) demuxer->chapters = malloc (32*sizeof(*demuxer->chapters)); else if (!(demuxer->num_chapters % 32)) demuxer->chapters = realloc (demuxer->chapters, (demuxer->num_chapters + 32) * sizeof(*demuxer->chapters)); demuxer->chapters[demuxer->num_chapters].start = start; demuxer->chapters[demuxer->num_chapters].end = end; demuxer->chapters[demuxer->num_chapters].name = strdup(name); return demuxer->num_chapters ++;}/** * \brief demuxer_seek_chapter() seeks to a chapter in two possible ways: * either using the demuxer->chapters structure set by the demuxer * or asking help to the stream layer (e.g. dvd) * \param chapter - chapter number wished - 0-based * \param mode 0: relative to current main pts, 1: absolute * \param seek_pts set by the function to the pts to seek to (if demuxer->chapters is set) * \param num_chapters number of chapters present (set by this function is param is not null) * \param chapter_name name of chapter found (set by this function is param is not null) * \return -1 on error, current chapter if successful */int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, int mode, float *seek_pts, int *num_chapters, char **chapter_name) { int ris; int current, total; sh_video_t *sh_video = demuxer->video->sh; sh_audio_t *sh_audio = demuxer->audio->sh; if (!demuxer->num_chapters || !demuxer->chapters) { if(!mode) { ris = stream_control(demuxer->stream, STREAM_CTRL_GET_CURRENT_CHAPTER, ¤t); if(ris == STREAM_UNSUPPORTED) return -1; chapter += current; } if(demuxer->video->sh) ds_free_packs(demuxer->video); if(demuxer->audio->sh) ds_free_packs(demuxer->audio); if(demuxer->sub->id >= 0) ds_free_packs(demuxer->sub); ris = stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_CHAPTER, &chapter); if(ris != STREAM_UNSUPPORTED) demux_control(demuxer, DEMUXER_CTRL_RESYNC, NULL); if(sh_video) { ds_fill_buffer(demuxer->video); resync_video_stream(sh_video); } if(sh_audio) { ds_fill_buffer(demuxer->audio); resync_audio_stream(sh_audio); } //exit status may be ok, but main() doesn't have to seek itself (because e.g. dvds depend on sectors, not on pts) *seek_pts = -1.0; if(num_chapters) { if(stream_control(demuxer->stream, STREAM_CTRL_GET_NUM_CHAPTERS, num_chapters) == STREAM_UNSUPPORTED) *num_chapters = 0; } if(chapter_name) { char *tmp = malloc(16); *chapter_name = NULL; if(num_chapters && *num_chapters && tmp) { sprintf(tmp, " of %3d", *num_chapters); *chapter_name = tmp; } } return (ris != STREAM_UNSUPPORTED ? chapter : -1); } else { //chapters structure is set in the demuxer total = demuxer->num_chapters; if (mode==1) { //absolute seeking current = chapter; } else { //relative seeking uint64_t now; now = (sh_video ? sh_video->pts : (sh_audio ? sh_audio->pts : 0.)) * 1000 + .5; for (current = total - 1; current >= 0; --current) { demux_chapter_t* chapter = demuxer->chapters + current; if (chapter->start <= now) break; } current += chapter; } if (current >= total) return -1; if (current < 0) current = 0; *seek_pts = demuxer->chapters[current].start / 1000.0; if(num_chapters) *num_chapters = demuxer->num_chapters; if(chapter_name) { if(demuxer->chapters[current].name) *chapter_name = strdup(demuxer->chapters[current].name); else *chapter_name = NULL; } return current; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?