📄 init.cxx
字号:
sadd_hhmmssf(line, &pos, width, a_pos); saddf(line, &pos, width, ") of %.1f (", len); sadd_hhmmssf(line, &pos, width, len); saddf(line, &pos, width, ") "); } } // Video time if (sh_video) saddf(line, &pos, width, "V:%6.1f ", sh_video->pts); // A-V sync if (sh_audio && sh_video) saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ", a_v, corr); // Video stats if (sh_video) saddf(line, &pos, width, "%3d/%3d ", (int)sh_video->num_frames, (int)sh_video->num_frames_decoded); // CPU usage if (sh_video) { if (sh_video->timer > 0.5) saddf(line, &pos, width, "%2d%% %2d%% %4.1f%% ", (int)(100.0*video_time_usage*playback_speed/(double)sh_video->timer), (int)(100.0*vout_time_usage*playback_speed/(double)sh_video->timer), (100.0*audio_time_usage*playback_speed/(double)sh_video->timer)); else saddf(line, &pos, width, "??%% ??%% ??,?%% "); } else if (sh_audio) { if (sh_audio->delay > 0.5) saddf(line, &pos, width, "%4.1f%% ", 100.0*audio_time_usage/(double)sh_audio->delay); else saddf(line, &pos, width, "??,?%% "); } // VO stats if (sh_video) saddf(line, &pos, width, "%d %d ", drop_frame_cnt, output_quality);#ifdef USE_STREAM_CACHE // cache stats if (stream_cache_size > 0) saddf(line, &pos, width, "%d%% ", cache_fill_status);#endif // other if (playback_speed != 1) saddf(line, &pos, width, "%4.2fx ", playback_speed); // end if (erase_to_end_of_line) { line[pos] = 0; mp_msg(MSGT_AVSYNC, MSGL_STATUS, "%s%s\r", line, erase_to_end_of_line); } else { memset(&line[pos], ' ', width - pos); line[width] = 0; mp_msg(MSGT_AVSYNC, MSGL_STATUS, "%s\r", line); } free(line);}/** * \brief build a chain of audio filters that converts the input format * to the ao's format, taking into account the current playback_speed. * \param sh_audio describes the requested input format of the chain. * \param ao_data describes the requested output format of the chain. */static int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data){ int new_srate; int result; if (!sh_audio) {#ifdef HAVE_NEW_GUI guiGetEvent(guiSetAfilter, (char *)NULL);#endif mixer.afilter = NULL; return 0; } new_srate = sh_audio->samplerate * playback_speed; if (new_srate != ao_data->samplerate) { // limits are taken from libaf/af_resample.c if (new_srate < 8000) new_srate = 8000; if (new_srate > 192000) new_srate = 192000; playback_speed = (float)new_srate / (float)sh_audio->samplerate; } result = init_audio_filters(sh_audio, new_srate, sh_audio->channels, sh_audio->sample_format, &ao_data->samplerate, &ao_data->channels, &ao_data->format, ao_data->outburst * 4, ao_data->buffersize); mixer.afilter = sh_audio->afilter;#ifdef HAVE_NEW_GUI guiGetEvent(guiSetAfilter, (char *)sh_audio->afilter);#endif return result;}#ifdef USE_SUB/** * \brief Log the currently displayed subtitle to a file * * Logs the current or last displayed subtitle together with filename * and time information to ~/.mplayer/subtitle_log * * Intended purpose is to allow convenient marking of bogus subtitles * which need to be fixed while watching the movie. */static void log_sub(void){ char *fname; FILE *f; int i; if (subdata == NULL || vo_sub_last == NULL) return; fname = get_path("subtitle_log"); f = fopen(fname, "a"); if (!f) return; fprintf(f, "----------------------------------------------------------\n"); if (subdata->sub_uses_time) { fprintf(f, "N: %s S: %02ld:%02ld:%02ld.%02ld E: %02ld:%02ld:%02ld.%02ld\n", filename, vo_sub_last->start/360000, (vo_sub_last->start/6000)%60, (vo_sub_last->start/100)%60, vo_sub_last->start%100, vo_sub_last->end/360000, (vo_sub_last->end/6000)%60, (vo_sub_last->end/100)%60, vo_sub_last->end%100); } else { fprintf(f, "N: %s S: %ld E: %ld\n", filename, vo_sub_last->start, vo_sub_last->end); } for (i = 0; i < vo_sub_last->lines; i++) { fprintf(f, "%s\n", vo_sub_last->text[i]); } fclose(f);}#endif /* USE_SUB *//// \defgroup OSDMsgStack OSD message stack//////@{#define OSD_MSG_TV_CHANNEL 0#define OSD_MSG_TEXT 1#define OSD_MSG_SUB_DELAY 2#define OSD_MSG_SPEED 3#define OSD_MSG_OSD_STATUS 4#define OSD_MSG_BAR 5#define OSD_MSG_PAUSE 6/// Base id for messages generated from the commmand to property bridge.#define OSD_MSG_PROPERTY 0x100typedef struct mp_osd_msg mp_osd_msg_t;struct mp_osd_msg { /// Previous message on the stack. mp_osd_msg_t* prev; /// Message text. char msg[64]; int id,level,started; /// Display duration in ms. unsigned time;};/// OSD message stack.static mp_osd_msg_t* osd_msg_stack = NULL;/** * \brief Add a message on the OSD message stack * * If a message with the same id is already present in the stack * it is pulled on top of the stack, otherwise a new message is created. * */static void set_osd_msg(int id, int level, int time, char* fmt, ...) { mp_osd_msg_t *msg,*last=NULL; va_list va; int r; // look if the id is already in the stack for(msg = osd_msg_stack ; msg && msg->id != id ; last = msg, msg = msg->prev); // not found: alloc it if(!msg) { msg = calloc(1,sizeof(mp_osd_msg_t)); msg->prev = osd_msg_stack; osd_msg_stack = msg; } else if(last) { // found, but it's not on top of the stack last->prev = msg->prev; msg->prev = osd_msg_stack; osd_msg_stack = msg; } // write the msg va_start(va,fmt); r = vsnprintf(msg->msg, 64, fmt, va); va_end(va); if(r >= 64) msg->msg[63] = 0; // set id and time msg->id = id; msg->level = level; msg->time = time; }/** * \brief Remove a message from the OSD stack * * This function can be used to get rid of a message right away. * */static void rm_osd_msg(int id) { mp_osd_msg_t *msg,*last=NULL; // Search for the msg for(msg = osd_msg_stack ; msg && msg->id != id ; last = msg, msg = msg->prev); if(!msg) return; // Detach it from the stack and free it if(last) last->prev = msg->prev; else osd_msg_stack = msg->prev; free(msg);}/** * \brief Remove all messages from the OSD stack * */static void clear_osd_msgs(void) { mp_osd_msg_t* msg = osd_msg_stack, *prev = NULL; while(msg) { prev = msg->prev; free(msg); msg = prev; } osd_msg_stack = NULL;}/** * \brief Get the current message from the OSD stack. * * This function decrements the message timer and destroys the old ones. * The message that should be displayed is returned (if any). * */static mp_osd_msg_t* get_osd_msg(void) { mp_osd_msg_t *msg,*prev,*last = NULL; static unsigned last_update = 0; unsigned now = GetTimerMS(); unsigned diff; char hidden_dec_done = 0; if(!last_update) last_update = now; diff = now >= last_update ? now - last_update : 0; last_update = now; // Look for the first message in the stack with high enough level. for(msg = osd_msg_stack ; msg ; last = msg, msg = prev) { prev = msg->prev; if(msg->level > osd_level && hidden_dec_done) continue; // The message has a high enough level or it is the first hidden one // in both cases we decrement the timer or kill it. if(!msg->started || msg->time > diff) { if(msg->started) msg->time -= diff; else msg->started = 1; // display it if(msg->level <= osd_level) return msg; hidden_dec_done = 1; continue; } // kill the message free(msg); if(last) { last->prev = prev; msg = last; } else { osd_msg_stack = prev; msg = NULL; } } // Nothing found return NULL;}// Make a define to test if we are using the term OSD without having// to #ifdef USE_OSD all the time.#ifdef USE_OSD#define use_term_osd (term_osd && !sh_video)#else#define use_term_osd (term_osd)#endif/** * \brief Display the OSD bar. * * Display the OSD bar or fall back on a simple message. * */void set_osd_bar(int type,char* name,double min,double max,double val) { if(osd_level < 1) return; #ifdef USE_OSD if(sh_video) { osd_visible = (GetTimerMS() + 1000) | 1; vo_osd_progbar_type = type; vo_osd_progbar_value = 256*(val-min)/(max-min); vo_osd_changed(OSDTYPE_PROGBAR); return; }#endif set_osd_msg(OSD_MSG_BAR,1,osd_duration,"%s: %d %%", name,ROUND(100*(val-min)/(max-min)));}/** * \brief Update the OSD message line. * * This function displays the current message on the vo OSD or on the term. * If the stack is empty and the OSD level is high enough the timer * is displayed (only on the vo OSD). * */static void update_osd_msg(void) { mp_osd_msg_t *msg; static char osd_text[64] = ""; static char osd_text_timer[64]; #ifdef USE_OSD // we need some mem for vo_osd_text vo_osd_text = (unsigned char*)osd_text;#endif // Look if we have a msg if((msg = get_osd_msg())) { if(strcmp(osd_text,msg->msg)) { strncpy((char*)osd_text, msg->msg, 63);#ifdef USE_OSD if(sh_video) vo_osd_changed(OSDTYPE_OSD); else #endif if(term_osd) printf("%s%s\n",term_osd_esc,msg->msg); } return; } #ifdef USE_OSD if(sh_video) { // fallback on the timer if(osd_level>=2) { int len = demuxer_get_time_length(demuxer); int percentage = -1; char percentage_text[10]; static int last_pts = -303; int pts = sh_video->pts; if(pts==last_pts-1) ++pts; else last_pts=pts; if (osd_show_percentage) percentage = demuxer_get_percent_pos(demuxer); if (percentage >= 0) snprintf(percentage_text, 9, " (%d%%)", percentage); else percentage_text[0] = 0; if (osd_level == 3) snprintf(osd_text_timer, 63, "%c %02d:%02d:%02d / %02d:%02d:%02d%s", osd_function,pts/3600,(pts/60)%60,pts%60, len/3600,(len/60)%60,len%60,percentage_text); else snprintf(osd_text_timer, 63, "%c %02d:%02d:%02d%s", osd_function,pts/3600,(pts/60)%60, pts%60,percentage_text); } else osd_text_timer[0]=0; // always decrement the percentage timer if(osd_show_percentage) osd_show_percentage--; if(strcmp(osd_text,osd_text_timer)) { strncpy(osd_text, osd_text_timer, 63); vo_osd_changed(OSDTYPE_OSD); } return; }#endif // Clear the term osd line if(term_osd && osd_text[0]) { osd_text[0] = 0; printf("%s\n",term_osd_esc); }}///@}// OSDMsgStack/// \defgroup Properties///@{/// \defgroup GeneralProperties General properties/// \ingroup Properties///@{/// OSD level (RW)static int mp_property_osdlevel(m_option_t* prop,int action,void* arg) { return m_property_choice(prop,action,arg,&osd_level);}/// Playback speed (RW)static int mp_property_playback_speed(m_option_t* prop,int action,void* arg) { switch(action) { case M_PROPERTY_SET: if(!arg) return 0; M_PROPERTY_CLAMP(prop,*(float*)arg); playback_speed = *(float*)arg; build_afilter_chain(sh_audio, &ao_data); return 1; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: playback_speed += (arg ? *(float*)arg : 0.1) * (action == M_PROPERTY_STEP_DOWN ? -1 : 1); M_PROPERTY_CLAMP(prop,playback_speed); build_afilter_chain(sh_audio, &ao_data); return 1; } return m_property_float_range(prop,action,arg,&playback_speed);}/// filename with path (RO)static int mp_property_path(m_option_t* prop,int action,void* arg) { return m_property_string_ro(prop,action,arg,filename);}/// filename without path (RO)static int mp_property_filename(m_option_t* prop,int action,void* arg) { char* f; if(!filename) return M_PROPERTY_UNAVAILABLE; if(((f = strrchr(filename,'/')) || (f = strrchr(filename,'\\'))) && f[1]) f++; else f = filename; return m_property_string_ro(prop,action,arg,f);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -