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, &current);            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 + -
显示快捷键?