void mp_ass_configure(ASS_Renderer *priv, struct MPOpts *opts, struct mp_osd_res *dim) { ass_set_frame_size(priv, dim->w, dim->h); ass_set_margins(priv, dim->mt, dim->mb, dim->ml, dim->mr); int set_use_margins = 0; #if LIBASS_VERSION >= 0x01010000 int set_sub_pos = 0; #endif float set_line_spacing = 0; float set_font_scale = 1; int set_hinting = 0; if (opts->ass_style_override) { set_use_margins = opts->ass_use_margins; #if LIBASS_VERSION >= 0x01010000 set_sub_pos = 100 - opts->sub_pos; #endif set_line_spacing = opts->ass_line_spacing; set_font_scale = opts->sub_scale; set_hinting = opts->ass_hinting & 3; // +4 was for no hinting if scaled } ass_set_use_margins(priv, set_use_margins); #if LIBASS_VERSION >= 0x01010000 ass_set_line_position(priv, set_sub_pos); #endif ass_set_font_scale(priv, set_font_scale); ass_set_hinting(priv, set_hinting); ass_set_line_spacing(priv, set_line_spacing); }
static void eosd_ass_update(struct mp_eosd_source *src, const struct mp_eosd_settings *res, double ts) { long long ts_ms = (ts + sub_delay) * 1000 + .5; ASS_Image *aimg; struct mp_eosd_image *img; if (res->changed || !src->initialized) { double dar = (double) (res->w - res->ml - res->mr) / (res->h - res->mt - res->mb); ass_configure(ass_renderer, res->w, res->h, res->unscaled); ass_set_margins(ass_renderer, res->mt, res->mb, res->ml, res->mr); ass_set_aspect_ratio(ass_renderer, dar, (double)res->srcw / res->srch); src->initialized = 1; } aimg = sub_visibility && ass_track && ts != MP_NOPTS_VALUE ? ass_mp_render_frame(ass_renderer, ass_track, ts_ms, &src->changed) : NULL; if (!aimg != !src->images) src->changed = 2; if (src->changed) { eosd_image_remove_all(src); while (aimg) { img = eosd_image_alloc(); img->w = aimg->w; img->h = aimg->h; img->bitmap = aimg->bitmap; img->stride = aimg->stride; img->color = aimg->color; img->dst_x = aimg->dst_x; img->dst_y = aimg->dst_y; eosd_image_append(src, img); aimg = aimg->next; } } prev_visibility = sub_visibility; }
ASS_Image* ass_mp_render_frame(ASS_Renderer *priv, ASS_Track* track, long long now, int* detect_change) { if (ass_force_reload) { ass_set_margins(priv, ass_top_margin, ass_bottom_margin, 0, 0); ass_set_use_margins(priv, ass_use_margins); ass_set_font_scale(priv, ass_font_scale); ass_force_reload = 0; } return ass_render_frame(priv, track, now, detect_change); }
void ass_configure(ASS_Renderer* priv, int w, int h, int unscaled) { int hinting; ass_set_frame_size(priv, w, h); ass_set_margins(priv, ass_top_margin, ass_bottom_margin, 0, 0); ass_set_use_margins(priv, ass_use_margins); ass_set_font_scale(priv, ass_font_scale); if (!unscaled && (ass_hinting & 4)) hinting = 0; else hinting = ass_hinting & 3; ass_set_hinting(priv, hinting); ass_set_line_spacing(priv, ass_line_spacing); }
void mp_ass_configure(ASS_Renderer *priv, struct MPOpts *opts, struct mp_osd_res *dim) { ass_set_frame_size(priv, dim->w, dim->h); ass_set_margins(priv, dim->mt, dim->mb, dim->ml, dim->mr); int set_use_margins = 0; #if LIBASS_VERSION >= 0x01010000 int set_sub_pos = 0; #endif float set_line_spacing = 0; float set_font_scale = 1; int set_hinting = 0; int set_force_override = 0; if (opts->ass_style_override) { set_use_margins = opts->ass_use_margins; #if LIBASS_VERSION >= 0x01010000 set_sub_pos = 100 - opts->sub_pos; #endif set_line_spacing = opts->ass_line_spacing; set_font_scale = opts->sub_scale; set_hinting = opts->ass_hinting; set_force_override = opts->ass_style_override == 3; } ass_set_use_margins(priv, set_use_margins); #if LIBASS_VERSION >= 0x01010000 ass_set_line_position(priv, set_sub_pos); #endif #if LIBASS_VERSION >= 0x01000000 ass_set_shaper(priv, opts->ass_shaper); #endif #if LIBASS_VERSION >= 0x01103000 ass_set_selective_style_override_enabled(priv, set_force_override); ASS_Style style = {0}; mp_ass_set_style(&style, 288, opts->sub_text_style); ass_set_selective_style_override(priv, &style); free(style.FontName); #endif ass_set_font_scale(priv, set_font_scale); ass_set_hinting(priv, set_hinting); ass_set_line_spacing(priv, set_line_spacing); }
CDVDSubtitlesLibass::CDVDSubtitlesLibass() { //Setting the font directory to the temp dir(where mkv fonts are extracted to) std::string strPath = "special://temp/fonts/"; CLog::Log(LOGINFO, "CDVDSubtitlesLibass: Creating ASS library structure"); m_library = ass_library_init(); if(!m_library) return; ass_set_message_cb(m_library, libass_log, this); CLog::Log(LOGINFO, "CDVDSubtitlesLibass: Initializing ASS library font settings"); // libass uses fontconfig (system lib) which is not wrapped // so translate the path before calling into libass ass_set_fonts_dir(m_library, CSpecialProtocol::TranslatePath(strPath).c_str()); ass_set_extract_fonts(m_library, 1); ass_set_style_overrides(m_library, NULL); CLog::Log(LOGINFO, "CDVDSubtitlesLibass: Initializing ASS Renderer"); m_renderer = ass_renderer_init(m_library); if(!m_renderer) return; //Setting default font to the Arial in \media\fonts (used if FontConfig fails) const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings(); strPath = URIUtils::AddFileToFolder("special://home/media/Fonts/", settings->GetString(CSettings::SETTING_SUBTITLES_FONT)); if (!XFILE::CFile::Exists(strPath)) strPath = URIUtils::AddFileToFolder("special://xbmc/media/Fonts/", settings->GetString(CSettings::SETTING_SUBTITLES_FONT)); int fc = !settings->GetBool(CSettings::SETTING_SUBTITLES_OVERRIDEASSFONTS); ass_set_margins(m_renderer, 0, 0, 0, 0); ass_set_use_margins(m_renderer, 0); ass_set_font_scale(m_renderer, 1); // libass uses fontconfig (system lib) which is not wrapped // so translate the path before calling into libass ass_set_fonts(m_renderer, CSpecialProtocol::TranslatePath(strPath).c_str(), "Arial", fc, NULL, 1); }
ASS_Image* CDVDSubtitlesLibass::RenderImage(int frameWidth, int frameHeight, int videoWidth, int videoHeight, int sourceWidth, int sourceHeight, double pts, int useMargin, double position, int *changes) { CSingleLock lock(m_section); if(!m_renderer || !m_track) { CLog::Log(LOGERROR, "CDVDSubtitlesLibass: %s - Missing ASS structs(m_track or m_renderer)", __FUNCTION__); return NULL; } double sar = (double)sourceWidth / sourceHeight; double dar = (double)videoWidth / videoHeight; ass_set_frame_size(m_renderer, frameWidth, frameHeight); int topmargin = (frameHeight - videoHeight) / 2; int leftmargin = (frameWidth - videoWidth) / 2; ass_set_margins(m_renderer, topmargin, topmargin, leftmargin, leftmargin); ass_set_use_margins(m_renderer, useMargin); ass_set_line_position(m_renderer, position); ass_set_aspect_ratio(m_renderer, dar, sar); return ass_render_frame(m_renderer, m_track, DVD_TIME_TO_MSEC(pts), changes); }
LibassConfiguration libass_configure(Configuration conf) { LibassConfiguration libass_conf; ASS_Library *library = ass_library_init(); if (library == NULL) { printf("Couldn't initialize ass library ...\n"); exit(EXIT_FAILURE); } libass_conf.library = library; ASS_Renderer *renderer = ass_renderer_init(library); if (renderer == NULL) { printf("Couldn't initialize ass library ...\n"); exit(EXIT_FAILURE); } ass_set_frame_size(renderer, conf.width, conf.height); if (conf.display_aspect != -1.0) ass_set_aspect_ratio(renderer, conf.display_aspect, ((double)conf.width) / ((double)conf.height)); ass_set_margins(renderer, 20, 20, 60, 60); ass_set_fonts(renderer, NULL, "Arial", 1, NULL, 1); ass_set_font_scale(renderer, conf.font_scale); libass_conf.renderer = renderer; return libass_conf; }
static void *ass_reader_thread(void *) { set_threadname("ass_reader_thread"); while (!sem_wait(&ass_sem)) { if (!ass_reader_running) break; ass_data *a = (ass_data *) ass_queue.pop(); if (!a) { if (!ass_reader_running) break; continue; } OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(ass_mutex); std::map<int,ASS_Track*>::iterator it = ass_map.find(a->pid); ASS_Track *track; if (it == ass_map.end()) { CFrameBuffer *fb = CFrameBuffer::getInstance(); int xres = fb->getScreenWidth(true); int yres = fb->getScreenHeight(true); if (!ass_library) { ass_library = ass_library_init(); ass_set_extract_fonts(ass_library, 1); ass_set_style_overrides(ass_library, NULL); ass_renderer = ass_renderer_init(ass_library); ass_set_frame_size(ass_renderer, xres, yres); ass_set_margins(ass_renderer, 3 * yres / 100, 3 * yres / 100, 3 * xres / 100, 3 * xres / 100); ass_set_use_margins(ass_renderer, 1); ass_set_hinting(ass_renderer, ASS_HINTING_LIGHT); ass_set_aspect_ratio(ass_renderer, 1.0, 1.0); ass_font = *sub_font_file; ass_set_fonts(ass_renderer, ass_font.c_str(), "Arial", 0, NULL, 1); } track = ass_new_track(ass_library); track->PlayResX = xres; track->PlayResY = yres; ass_size = sub_font_size; ass_set_font_scale(ass_renderer, ((double) ass_size)/ASS_CUSTOM_FONT_SIZE); if (a->c->subtitle_header) { std::string ass_hdr = ass_subtitle_header_default(); if (ass_hdr.compare((char*) a->c->subtitle_header)) { ass_process_codec_private(track, (char *) a->c->subtitle_header, a->c->subtitle_header_size); } else { // This is the FFMPEG default ASS header. Use something more suitable instead: ass_hdr = ass_subtitle_header_custom(); ass_process_codec_private(track, (char *) ass_hdr.c_str(), ass_hdr.length()); } } ass_map[a->pid] = track; if (a->pid == dvbsub_pid) ass_track = track; //fprintf(stderr, "### got subtitle track %d, subtitle header: \n---\n%s\n---\n", pid, c->subtitle_header); } else track = it->second; for (unsigned int i = 0; i < a->sub.num_rects; i++) if (a->sub.rects[i]->ass) ass_process_data(track, a->sub.rects[i]->ass, strlen(a->sub.rects[i]->ass)); avsubtitle_free(&a->sub); delete a; } ass_reader_running = false; pthread_exit(NULL); }
static int control(struct vf_instance_s* vf, int request, void* data) { switch(request){ case VFCTRL_GET_DEINTERLACE: { if(!video_out) return CONTROL_FALSE; // vo not configured? return(video_out->control(VOCTRL_GET_DEINTERLACE, data) == VO_TRUE) ? CONTROL_TRUE : CONTROL_FALSE; } case VFCTRL_SET_DEINTERLACE: { if(!video_out) return CONTROL_FALSE; // vo not configured? return(video_out->control(VOCTRL_SET_DEINTERLACE, data) == VO_TRUE) ? CONTROL_TRUE : CONTROL_FALSE; } case VFCTRL_DRAW_OSD: if(!vo_config_count) return CONTROL_FALSE; // vo not configured? video_out->draw_osd(); return CONTROL_TRUE; case VFCTRL_FLIP_PAGE: { if(!vo_config_count) return CONTROL_FALSE; // vo not configured? video_out->flip_page(); return CONTROL_TRUE; } case VFCTRL_SET_EQUALIZER: { vf_equalizer_t *eq=data; if(!vo_config_count) return CONTROL_FALSE; // vo not configured? return((video_out->control(VOCTRL_SET_EQUALIZER, eq->item, eq->value) == VO_TRUE) ? CONTROL_TRUE : CONTROL_FALSE); } case VFCTRL_GET_EQUALIZER: { vf_equalizer_t *eq=data; if(!vo_config_count) return CONTROL_FALSE; // vo not configured? return((video_out->control(VOCTRL_GET_EQUALIZER, eq->item, &eq->value) == VO_TRUE) ? CONTROL_TRUE : CONTROL_FALSE); } #ifdef USE_ASS case VFCTRL_INIT_EOSD: { vf->priv->ass_priv = ass_renderer_init((ass_library_t*)data); if (!vf->priv->ass_priv) return CONTROL_FALSE; ass_configure_fonts(vf->priv->ass_priv); vf->priv->prev_visibility = 0; return CONTROL_TRUE; } case VFCTRL_DRAW_EOSD: { mp_eosd_images_t images = {NULL, 2}; double pts = vf->priv->pts; if (!vo_config_count || !vf->priv->ass_priv) return CONTROL_FALSE; if (sub_visibility && vf->priv->ass_priv && ass_track && (pts != MP_NOPTS_VALUE)) { mp_eosd_res_t res; memset(&res, 0, sizeof(res)); if (video_out->control(VOCTRL_GET_EOSD_RES, &res) == VO_TRUE) { ass_set_frame_size(vf->priv->ass_priv, res.w, res.h); ass_set_margins(vf->priv->ass_priv, res.mt, res.mb, res.ml, res.mr); ass_set_aspect_ratio(vf->priv->ass_priv, (double)res.w / res.h); } images.imgs = ass_render_frame(vf->priv->ass_priv, ass_track, (pts+sub_delay) * 1000 + .5, &images.changed); if (!vf->priv->prev_visibility) images.changed = 2; vf->priv->prev_visibility = 1; } else vf->priv->prev_visibility = 0; vf->priv->prev_visibility = sub_visibility; return (video_out->control(VOCTRL_DRAW_EOSD, &images) == VO_TRUE) ? CONTROL_TRUE : CONTROL_FALSE; } #endif case VFCTRL_GET_PTS: { *(double *)data = vf->priv->pts; return CONTROL_TRUE; } } // return video_out->control(request,data); return CONTROL_UNKNOWN; }
static void configure_ass(struct sd *sd, struct mp_osd_res *dim, bool converted, ASS_Track *track) { struct MPOpts *opts = sd->opts; struct sd_ass_priv *ctx = sd->priv; ASS_Renderer *priv = ctx->ass_renderer; ass_set_frame_size(priv, dim->w, dim->h); ass_set_margins(priv, dim->mt, dim->mb, dim->ml, dim->mr); bool set_use_margins = false; int set_sub_pos = 0; float set_line_spacing = 0; float set_font_scale = 1; int set_hinting = 0; bool set_scale_with_window = false; bool set_scale_by_window = true; bool total_override = false; // With forced overrides, apply the --sub-* specific options if (converted || opts->ass_style_override == 3) { set_scale_with_window = opts->sub_scale_with_window; set_use_margins = opts->sub_use_margins; set_scale_by_window = opts->sub_scale_by_window; total_override = true; } else { set_scale_with_window = opts->ass_scale_with_window; set_use_margins = opts->ass_use_margins; } if (converted || opts->ass_style_override) { set_sub_pos = 100 - opts->sub_pos; set_line_spacing = opts->ass_line_spacing; set_hinting = opts->ass_hinting; set_font_scale = opts->sub_scale; } if (set_scale_with_window) { int vidh = dim->h - (dim->mt + dim->mb); set_font_scale *= dim->h / (float)MPMAX(vidh, 1); } if (!set_scale_by_window) { double factor = dim->h / 720.0; if (factor != 0.0) set_font_scale /= factor; } ass_set_use_margins(priv, set_use_margins); ass_set_line_position(priv, set_sub_pos); ass_set_shaper(priv, opts->ass_shaper); int set_force_flags = 0; if (total_override) set_force_flags |= ASS_OVERRIDE_BIT_STYLE | ASS_OVERRIDE_BIT_FONT_SIZE; if (opts->ass_style_override == 4) set_force_flags |= ASS_OVERRIDE_BIT_FONT_SIZE; ass_set_selective_style_override_enabled(priv, set_force_flags); ASS_Style style = {0}; mp_ass_set_style(&style, 288, opts->sub_text_style); ass_set_selective_style_override(priv, &style); free(style.FontName); if (converted && track->default_style < track->n_styles) { mp_ass_set_style(track->styles + track->default_style, track->PlayResY, opts->sub_text_style); } ass_set_font_scale(priv, set_font_scale); ass_set_hinting(priv, set_hinting); ass_set_line_spacing(priv, set_line_spacing); }
static void VS_CC assInit(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi) { AssData *d = (AssData *) * instanceData; vsapi->setVideoInfo(d->vi, 2, node); d->ass_library = ass_library_init(); if(!d->ass_library) { vsapi->setError(out, "failed to initialize ASS library"); return; } ass_set_message_cb(d->ass_library, assDebugCallback, (void *)d->debuglevel); ass_set_extract_fonts(d->ass_library, 0); ass_set_style_overrides(d->ass_library, 0); d->ass_renderer = ass_renderer_init(d->ass_library); if(!d->ass_renderer) { vsapi->setError(out, "failed to initialize ASS renderer"); return; } ass_set_font_scale(d->ass_renderer, d->scale); ass_set_frame_size(d->ass_renderer, d->vi[0].width, d->vi[0].height); ass_set_margins(d->ass_renderer, d->margins[0], d->margins[1], d->margins[2], d->margins[3]); ass_set_use_margins(d->ass_renderer, 1); if(d->linespacing) ass_set_line_spacing(d->ass_renderer, d->linespacing); if(d->sar) { ass_set_aspect_ratio(d->ass_renderer, (double)d->vi[0].width / d->vi[0].height * d->sar, 1); } if(d->fontdir) ass_set_fonts_dir(d->ass_library, d->fontdir); ass_set_fonts(d->ass_renderer, NULL, NULL, 1, NULL, 1); if(d->file == NULL) { char *str, *text, x[16], y[16]; size_t siz; const char *fmt = "[Script Info]\n" "ScriptType: v4.00+\n" "PlayResX: %s\n" "PlayResY: %s\n" "[V4+ Styles]\n" "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n" "Style: Default,%s\n" "[Events]\n" "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n" "Dialogue: 0,0:00:00.00,0:00:10.00,Default,,0,0,0,,%s\n"; sprintf(x, "%d", d->vi[0].width); sprintf(y, "%d", d->vi[0].height); text = strrepl(d->text, "\n", "\\N"); siz = (strlen(fmt) + strlen(x) + strlen(y) + strlen(d->style) + strlen(text)) * sizeof(char); str = malloc(siz); sprintf(str, fmt, x, y, d->style, text); free(text); d->ass = ass_new_track(d->ass_library); ass_process_data(d->ass, str, strlen(str)); free(str); } else { d->ass = ass_read_file(d->ass_library, (char *)d->file, (char *)d->charset); } if(!d->ass) { vsapi->setError(out, "unable to parse input file"); return; } }