void update_subtitles(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; if (!(mpctx->initialized_flags & INITIALIZED_SUB)) return; struct track *track = mpctx->current_track[STREAM_SUB]; struct dec_sub *dec_sub = mpctx->d_sub; assert(track && dec_sub); if (mpctx->d_video) { struct mp_image_params params = mpctx->d_video->vf_input; if (params.imgfmt) sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, ¶ms); } mpctx->osd->video_offset = track->under_timeline ? mpctx->video_offset : 0; double refpts_s = mpctx->playback_pts - mpctx->osd->video_offset; double curpts_s = refpts_s + opts->sub_delay; if (!track->preloaded && track->stream) { struct sh_stream *sh_stream = track->stream; bool interleaved = is_interleaved(mpctx, track); assert(sh_stream->sub->dec_sub == dec_sub); while (1) { if (interleaved && !demux_has_packet(sh_stream)) break; double subpts_s = demux_get_next_pts(sh_stream); if (!demux_has_packet(sh_stream)) break; if (subpts_s > curpts_s) { MP_DBG(mpctx, "Sub early: c_pts=%5.3f s_pts=%5.3f\n", curpts_s, subpts_s); // Libass handled subs can be fed to it in advance if (!sub_accept_packets_in_advance(dec_sub)) break; // Try to avoid demuxing whole file at once if (subpts_s > curpts_s + 1 && !interleaved) break; } struct demux_packet *pkt = demux_read_packet(sh_stream); MP_DBG(mpctx, "Sub: c_pts=%5.3f s_pts=%5.3f duration=%5.3f len=%d\n", curpts_s, pkt->pts, pkt->duration, pkt->len); sub_decode(dec_sub, pkt); talloc_free(pkt); } } if (!mpctx->osd->render_bitmap_subs || !mpctx->video_out) set_osd_subtitle(mpctx, sub_get_text(dec_sub, curpts_s)); }
void update_osd_sub_state(struct MPContext *mpctx, int order, struct osd_sub_state *out_state) { struct MPOpts *opts = mpctx->opts; struct track *track = mpctx->current_track[order][STREAM_SUB]; struct dec_sub *dec_sub = mpctx->d_sub[order]; int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB; bool textsub = dec_sub && sub_has_get_text(dec_sub); struct osd_sub_state state = { .dec_sub = dec_sub, // Decides whether to use OSD path or normal subtitle rendering path. .render_bitmap_subs = opts->ass_enabled || !textsub, .video_offset = get_track_video_offset(mpctx, track), }; // Secondary subs are rendered with the "text" renderer to transform them // to toptitles. if (order == 1 && textsub) state.render_bitmap_subs = false; if (!mpctx->current_track[0][STREAM_VIDEO]) state.render_bitmap_subs = false; osd_set_sub(mpctx->osd, obj, &state); if (out_state) *out_state = state; } static void update_subtitle(struct MPContext *mpctx, int order) { struct MPOpts *opts = mpctx->opts; struct track *track = mpctx->current_track[order][STREAM_SUB]; struct dec_sub *dec_sub = mpctx->d_sub[order]; if (!track || !dec_sub) return; int obj = order ? OSDTYPE_SUB2 : OSDTYPE_SUB; if (mpctx->d_video) { struct mp_image_params params = mpctx->d_video->vfilter->override_params; if (params.imgfmt) sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, ¶ms); } struct osd_sub_state state; update_osd_sub_state(mpctx, order, &state); double refpts_s = mpctx->playback_pts - state.video_offset; double curpts_s = refpts_s - opts->sub_delay; if (!track->preloaded && track->stream) { struct sh_stream *sh_stream = track->stream; bool interleaved = is_interleaved(mpctx, track); assert(sh_stream->sub->dec_sub == dec_sub); while (1) { if (interleaved && !demux_has_packet(sh_stream)) break; double subpts_s = demux_get_next_pts(sh_stream); if (!demux_has_packet(sh_stream)) break; if (subpts_s > curpts_s) { MP_DBG(mpctx, "Sub early: c_pts=%5.3f s_pts=%5.3f\n", curpts_s, subpts_s); // Libass handled subs can be fed to it in advance if (!sub_accept_packets_in_advance(dec_sub)) break; // Try to avoid demuxing whole file at once if (subpts_s > curpts_s + 1 && !interleaved) break; } struct demux_packet *pkt = demux_read_packet(sh_stream); MP_DBG(mpctx, "Sub: c_pts=%5.3f s_pts=%5.3f duration=%5.3f len=%d\n", curpts_s, pkt->pts, pkt->duration, pkt->len); sub_decode(dec_sub, pkt); talloc_free(pkt); } } // Handle displaying subtitles on terminal; never done for secondary subs if (order == 0) { if (!state.render_bitmap_subs || !mpctx->video_out) set_osd_subtitle(mpctx, sub_get_text(dec_sub, curpts_s)); } else if (order == 1) { osd_set_text(mpctx->osd, obj, sub_get_text(dec_sub, curpts_s)); } } void update_subtitles(struct MPContext *mpctx) { update_subtitle(mpctx, 0); update_subtitle(mpctx, 1); }