csri_inst *csri_open_mem(csri_rend *renderer, const void *data, size_t length, struct csri_openflag *flags) { csri_inst *rv; if (renderer != &csri_libass) return NULL; rv = (csri_inst *)malloc(sizeof(csri_inst)); if (!rv) return NULL; rv->ass_renderer = ass_renderer_init(renderer->ass_library); if (!rv->ass_renderer) { free(rv); return NULL; } ass_set_font_scale(rv->ass_renderer, 1.); ass_set_fonts(rv->ass_renderer, NULL, "Sans"); rv->ass_track = ass_read_memory(csri_libass.ass_library, (void *)data, length, "UTF-8"); if (!rv->ass_track) { ass_renderer_done(rv->ass_renderer); free(rv); return NULL; } return rv; }
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 csri_inst *libass_init_stream(csri_rend *renderer, const void *header, size_t headerlen, struct csri_openflag *flags) { csri_inst *rv; if (renderer != &csri_libass) return NULL; rv = (csri_inst *)malloc(sizeof(csri_inst)); if (!rv) return NULL; rv->ass_renderer = ass_renderer_init(renderer->ass_library); if (!rv->ass_renderer) { free(rv); return NULL; } ass_set_font_scale(rv->ass_renderer, 1.); ass_set_fonts(rv->ass_renderer, NULL, "Sans"); rv->ass_track = ass_new_track(csri_libass.ass_library); if (!rv->ass_track) { ass_renderer_done(rv->ass_renderer); free(rv); return NULL; } ass_process_codec_private(rv->ass_track, (void *)header, headerlen); return rv; }
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); }
static void ass_configure(ASS_Renderer* priv, int w, int h, int unscaled) { int hinting; ass_set_frame_size(priv, w, h); 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 ass_configure(ass_renderer_t* 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); }
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; }
/***************************************************************************** * Create: Open libass decoder. *****************************************************************************/ static int Create( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_SSA ) return VLC_EGENERIC; p_dec->pf_decode_sub = DecodeBlock; p_dec->pf_flush = Flush; p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; /* */ vlc_mutex_init( &p_sys->lock ); p_sys->i_refcount = 1; memset( &p_sys->fmt, 0, sizeof(p_sys->fmt) ); p_sys->i_max_stop = VLC_TS_INVALID; p_sys->p_library = NULL; p_sys->p_renderer = NULL; p_sys->p_track = NULL; /* Create libass library */ ASS_Library *p_library = p_sys->p_library = ass_library_init(); if( !p_library ) { msg_Warn( p_dec, "Libass library creation failed" ); DecSysRelease( p_sys ); return VLC_EGENERIC; } /* load attachments */ input_attachment_t **pp_attachments; int i_attachments; if( decoder_GetInputAttachments( p_dec, &pp_attachments, &i_attachments )) { i_attachments = 0; pp_attachments = NULL; } for( int k = 0; k < i_attachments; k++ ) { input_attachment_t *p_attach = pp_attachments[k]; bool found = false; /* Check mimetype*/ if( !strcasecmp( p_attach->psz_mime, "application/x-truetype-font" ) ) found = true; /* Then extension */ else if( !found && strlen( p_attach->psz_name ) > 4 ) { char *ext = p_attach->psz_name + strlen( p_attach->psz_name ) - 4; if( !strcasecmp( ext, ".ttf" ) || !strcasecmp( ext, ".otf" ) || !strcasecmp( ext, ".ttc" ) ) found = true; } if( found ) { msg_Dbg( p_dec, "adding embedded font %s", p_attach->psz_name ); ass_add_font( p_sys->p_library, p_attach->psz_name, p_attach->p_data, p_attach->i_data ); } vlc_input_attachment_Delete( p_attach ); } free( pp_attachments ); ass_set_extract_fonts( p_library, true ); ass_set_style_overrides( p_library, NULL ); /* Create the renderer */ ASS_Renderer *p_renderer = p_sys->p_renderer = ass_renderer_init( p_library ); if( !p_renderer ) { msg_Warn( p_dec, "Libass renderer creation failed" ); DecSysRelease( p_sys ); return VLC_EGENERIC; } ass_set_use_margins( p_renderer, false); //if( false ) // ass_set_margins( p_renderer, int t, int b, int l, int r); ass_set_hinting( p_renderer, ASS_HINTING_LIGHT ); ass_set_font_scale( p_renderer, 1.0 ); ass_set_line_spacing( p_renderer, 0.0 ); #if defined( __ANDROID__ ) const char *psz_font = "/system/fonts/DroidSans-Bold.ttf"; const char *psz_family = "Droid Sans Bold"; #elif defined( __APPLE__ ) const char *psz_font = NULL; /* We don't ship a default font with VLC */ const char *psz_family = "Helvetica Neue"; /* Use HN if we can't find anything more suitable - Arial is not on all Apple platforms */ #else const char *psz_font = NULL; /* We don't ship a default font with VLC */ const char *psz_family = "Arial"; /* Use Arial if we can't find anything more suitable */ #endif #ifdef HAVE_FONTCONFIG #if defined(_WIN32) dialog_progress_bar_t *p_dialog = dialog_ProgressCreate( p_dec, _("Building font cache"), _( "Please wait while your font cache is rebuilt.\n" "This should take less than a minute." ), NULL ); #endif ass_set_fonts( p_renderer, psz_font, psz_family, 1, NULL, 1 ); // setup default font/family #if defined(_WIN32) if( p_dialog ) { dialog_ProgressSet( p_dialog, NULL, 1.0 ); dialog_ProgressDestroy( p_dialog ); } #endif #else ass_set_fonts( p_renderer, psz_font, psz_family, 1, NULL, 1 ); #endif /* Add a track */ ASS_Track *p_track = p_sys->p_track = ass_new_track( p_sys->p_library ); if( !p_track ) { DecSysRelease( p_sys ); return VLC_EGENERIC; } ass_process_codec_private( p_track, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); p_dec->fmt_out.i_cat = SPU_ES; p_dec->fmt_out.i_codec = VLC_CODEC_RGBA; return VLC_SUCCESS; }
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); }
int main(int argc, char *argv[]) { POINT mouse; //while (true) { GetCursorPos(&mouse); printf("\r%d-%d ", mouse.x, mouse.y); } return interlace_RGB(); return matrix(); // char URI[] = "//mnt/sdcard/%E9%98%BF%E4%B8%BD%E4%BA%9A%E5%A8%9C%E5%90%89%E5%88%A9%E6%96%AF-%20Shake%E8%8B%B9%E6%9E%9C.3dv"; char URI[] = "//mnt/sdcard/HELLO!.3dv"; char decoded_URI[1024]; URIDecode(URI, decoded_URI, sizeof(decoded_URI)); char k = 0xef; bool a = k == 0xef; const int frame_w = 1920; const int frame_h = 1080; setlocale(LC_ALL, "CHS"); if (argc < 4) { printf("usage: %s <image file> <subtitle file> <time>\n", argv[0]); exit(1); } char *imgfile = argv[1]; char *subfile = argv[2]; double tm = strtod(argv[3], 0); FILE * f = fopen(subfile, "rb"); fseek(f, 0, SEEK_END); int file_size = ftell(f); fseek(f, 0, SEEK_SET); char *src = (char*)malloc(file_size); char *utf8 = (char*)malloc(file_size*3); fread(src, 1, file_size, f); fclose(f); int utf8_size = ConvertToUTF8(src, file_size, utf8, file_size*3); ass_library = ass_library_init(); if (!ass_library) { printf("ass_library_init failed!\n"); exit(1); } //ass_set_message_cb(ass_library, msg_callback, NULL); //ass_set_extract_fonts(ass_library, 0); //ass_set_style_overrides(ass_library, NULL); ass_renderer = ass_renderer_init(ass_library); if (!ass_renderer) { printf("ass_renderer_init failed!\n"); exit(1); } ass_set_frame_size(ass_renderer, frame_w, frame_h); ass_set_font_scale(ass_renderer, 1.0); //ass_set_hinting(ass_renderer, ASS_HINTING_NORMAL); ass_set_fonts(ass_renderer, "Arial", "Sans", 1, "Z:\\fonts.conf", 1); ASS_Track *track = ass_read_memory(ass_library, utf8, utf8_size, NULL); free(src); free(utf8); if (!track) { printf("track init failed!\n"); return 1; } ASS_Image *img = NULL; int n = 0; int changed = 0; image_t *frame = gen_image(frame_w, frame_h); int n2 = 0; int l = GetTickCount(); timeBeginPeriod(1); for(int i=0; i<int(tm*1000); i+=40) { img = ass_render_frame(ass_renderer, track, i, &changed); if (n==0) l = GetTickCount(); if (changed && img) { int l = timeGetTime(); n++; memset(frame->buffer, 63, frame->stride * frame->height); blend(frame, img); wchar_t pathname[MAX_PATH]; wsprintfW(pathname, L"Z:\\ass%02d.bmp", n); save_bitmap((DWORD*)frame->buffer, pathname, frame_w, frame_h); //printf("\rrender cost %dms.\t\t\n", timeGetTime()-l); } n2 ++; if (i%10000 == 0) printf("\r%d/%d ms rendered, %d frame output.", i, int(tm*1000), n); } ass_free_track(track); ass_renderer_done(ass_renderer); ass_library_done(ass_library); free(frame->buffer); free(frame); return 0; }
static ass_handle_t *AssHandleHold( decoder_t *p_dec ) { vlc_mutex_lock( &libass_lock ); ass_handle_t *p_ass = NULL; ASS_Library *p_library = NULL; ASS_Renderer *p_renderer = NULL; vlc_value_t val; var_Create( p_dec->p_libvlc, "libass-handle", VLC_VAR_ADDRESS ); if( var_Get( p_dec->p_libvlc, "libass-handle", &val ) ) val.p_address = NULL; if( val.p_address ) { p_ass = val.p_address; p_ass->i_refcount++; vlc_mutex_unlock( &libass_lock ); return p_ass; } /* */ p_ass = malloc( sizeof(*p_ass) ); if( !p_ass ) goto error; /* */ p_ass->p_libvlc = VLC_OBJECT(p_dec->p_libvlc); p_ass->i_refcount = 1; /* Create libass library */ p_ass->p_library = p_library = ass_library_init(); if( !p_library ) goto error; /* load attachments */ input_attachment_t **pp_attachments; int i_attachments; if( decoder_GetInputAttachments( p_dec, &pp_attachments, &i_attachments )) { i_attachments = 0; pp_attachments = NULL; } for( int k = 0; k < i_attachments; k++ ) { input_attachment_t *p_attach = pp_attachments[k]; if( !strcasecmp( p_attach->psz_mime, "application/x-truetype-font" ) ) { msg_Dbg( p_dec, "adding embedded font %s", p_attach->psz_name ); ass_add_font( p_ass->p_library, p_attach->psz_name, p_attach->p_data, p_attach->i_data ); } vlc_input_attachment_Delete( p_attach ); } free( pp_attachments ); ass_set_extract_fonts( p_library, true ); ass_set_style_overrides( p_library, NULL ); /* Create the renderer */ p_ass->p_renderer = p_renderer = ass_renderer_init( p_library ); if( !p_renderer ) goto error; ass_set_use_margins( p_renderer, false); //if( false ) // ass_set_margins( p_renderer, int t, int b, int l, int r); ass_set_hinting( p_renderer, ASS_HINTING_LIGHT ); ass_set_font_scale( p_renderer, 1.0 ); ass_set_line_spacing( p_renderer, 0.0 ); const char *psz_font = NULL; /* We don't ship a default font with VLC */ const char *psz_family = "Arial"; /* Use Arial if we can't find anything more suitable */ #ifdef HAVE_FONTCONFIG #if defined(WIN32) dialog_progress_bar_t *p_dialog = dialog_ProgressCreate( p_dec, _("Building font cache"), _( "Please wait while your font cache is rebuilt.\n" "This should take less than a minute." ), NULL ); if( p_dialog ) dialog_ProgressSet( p_dialog, NULL, 0.2 ); #endif #if defined( LIBASS_VERSION ) && LIBASS_VERSION >= 0x00907000 ass_set_fonts( p_renderer, psz_font, psz_family, true, NULL, 1 ); // setup default font/family #else ass_set_fonts( p_renderer, psz_font, psz_family ); // setup default font/family #endif #ifdef WIN32 if( p_dialog ) { dialog_ProgressSet( p_dialog, NULL, 1.0 ); dialog_ProgressDestroy( p_dialog ); p_dialog = NULL; } #endif #else /* FIXME you HAVE to give him a font if no fontconfig */ #if defined( LIBASS_VERSION ) && LIBASS_VERSION >= 0x00907000 ass_set_fonts( p_renderer, psz_font, psz_family, false, NULL, 1 ); #else ass_set_fonts_nofc( p_renderer, psz_font, psz_family ); #endif #endif memset( &p_ass->fmt, 0, sizeof(p_ass->fmt) ); /* */ val.p_address = p_ass; var_Set( p_dec->p_libvlc, "libass-handle", val ); /* */ vlc_mutex_unlock( &libass_lock ); return p_ass; error: if( p_renderer ) ass_renderer_done( p_renderer ); if( p_library ) ass_library_done( p_library ); msg_Warn( p_dec, "Libass creation failed" ); free( p_ass ); vlc_mutex_unlock( &libass_lock ); return NULL; }
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; } }
/***************************************************************************** * Create: Open libass decoder. *****************************************************************************/ static int Create( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_SSA ) return VLC_EGENERIC; p_dec->pf_decode_sub = DecodeBlock; p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; /* */ vlc_mutex_init( &p_sys->lock ); p_sys->i_refcount = 1; memset( &p_sys->fmt, 0, sizeof(p_sys->fmt) ); p_sys->i_max_stop = VLC_TS_INVALID; p_sys->p_library = NULL; p_sys->p_renderer = NULL; p_sys->p_track = NULL; /* Create libass library */ ASS_Library *p_library = p_sys->p_library = ass_library_init(); if( !p_library ) { msg_Warn( p_dec, "Libass library creation failed" ); DecSysRelease( p_sys ); return VLC_EGENERIC; } /* load attachments */ input_attachment_t **pp_attachments; int i_attachments; if( decoder_GetInputAttachments( p_dec, &pp_attachments, &i_attachments )) { i_attachments = 0; pp_attachments = NULL; } for( int k = 0; k < i_attachments; k++ ) { input_attachment_t *p_attach = pp_attachments[k]; if( !strcasecmp( p_attach->psz_mime, "application/x-truetype-font" ) ) { msg_Dbg( p_dec, "adding embedded font %s", p_attach->psz_name ); ass_add_font( p_sys->p_library, p_attach->psz_name, p_attach->p_data, p_attach->i_data ); } vlc_input_attachment_Delete( p_attach ); } free( pp_attachments ); ass_set_extract_fonts( p_library, true ); ass_set_style_overrides( p_library, NULL ); /* Create the renderer */ ASS_Renderer *p_renderer = p_sys->p_renderer = ass_renderer_init( p_library ); if( !p_renderer ) { msg_Warn( p_dec, "Libass renderer creation failed" ); DecSysRelease( p_sys ); return VLC_EGENERIC; } ass_set_use_margins( p_renderer, false); //if( false ) // ass_set_margins( p_renderer, int t, int b, int l, int r); ass_set_hinting( p_renderer, ASS_HINTING_LIGHT ); ass_set_font_scale( p_renderer, 1.0 ); ass_set_line_spacing( p_renderer, 0.0 ); const char *psz_font = NULL; /* We don't ship a default font with VLC */ const char *psz_family = "Arial"; /* Use Arial if we can't find anything more suitable */ #ifdef ANDROID /* is this useful? */ ass_set_fonts_dir( p_library, "/system/fonts" ); /* don't crash libass */ psz_font = "/system/fonts/DroidSansFallback.ttf"; #endif #ifdef HAVE_FONTCONFIG #if defined(WIN32) dialog_progress_bar_t *p_dialog = dialog_ProgressCreate( p_dec, _("Building font cache"), _( "Please wait while your font cache is rebuilt.\n" "This should take less than a minute." ), NULL ); if( p_dialog ) dialog_ProgressSet( p_dialog, NULL, 0.2 ); #endif ass_set_fonts( p_renderer, psz_font, psz_family, true, NULL, 1 ); // setup default font/family #ifdef WIN32 if( p_dialog ) { dialog_ProgressSet( p_dialog, NULL, 1.0 ); dialog_ProgressDestroy( p_dialog ); } #endif #else /* FIXME you HAVE to give him a font if no fontconfig */ ass_set_fonts( p_renderer, psz_font, psz_family, false, NULL, 1 ); #endif /* Add a track */ ASS_Track *p_track = p_sys->p_track = ass_new_track( p_sys->p_library ); if( !p_track ) { DecSysRelease( p_sys ); return VLC_EGENERIC; } ass_process_codec_private( p_track, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); p_dec->fmt_out.i_cat = SPU_ES; p_dec->fmt_out.i_codec = VLC_CODEC_RGBA; return VLC_SUCCESS; }
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 void* dvbsub_thread(void* /*arg*/) { struct timespec restartWait; struct timeval now; set_threadname("dvbsub:main"); sub_debug.print(Debug::VERBOSE, "%s started\n", __FUNCTION__); if (!dvbSubtitleConverter) dvbSubtitleConverter = new cDvbSubtitleConverter; int timeout = 1000000; #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE CFrameBuffer *fb = CFrameBuffer::getInstance(); int xres = fb->getScreenWidth(true); int yres = fb->getScreenHeight(true); int clr_x0 = xres, clr_y0 = yres, clr_x1 = 0, clr_y1 = 0; uint32_t colortable[256]; memset(colortable, 0, sizeof(colortable)); uint32_t last_color = 0; #endif while(dvbsub_running) { #if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE if (ass_track) { usleep(100000); // FIXME ... should poll instead OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(ass_mutex); if (!ass_track) continue; if (ass_size != sub_font_size) { ass_size = sub_font_size; ass_set_font_scale(ass_renderer, ((double) ass_size)/ASS_CUSTOM_FONT_SIZE); } int detect_change = 0; int64_t pts; getPlayerPts(&pts); ASS_Image *image = ass_render_frame(ass_renderer, ass_track, pts/90, &detect_change); if (detect_change) { if (clr_x1 && clr_y1) { fb->paintBox(clr_x0, clr_y0, clr_x1 + 1, clr_y1 + 1, 0); clr_x0 = xres; clr_y0 = yres; clr_x1 = clr_y1 = 0; } while (image) { if (last_color != image->color) { last_color = image->color; uint32_t c = last_color >> 8, a = 255 - (last_color & 0xff); for (int i = 0; i < 256; i++) { uint32_t k = (a * i) >> 8; colortable[i] = k ? (c | (k << 24)) : 0; } } if (image->w && image->h && image->dst_x > -1 && image->dst_x + image->w < xres && image->dst_y > -1 && image->dst_y + image->h < yres) { if (image->dst_x < clr_x0) clr_x0 = image->dst_x; if (image->dst_y < clr_y0) clr_y0 = image->dst_y; if (image->dst_x + image->w > clr_x1) clr_x1 = image->dst_x + image->w; if (image->dst_y + image->h > clr_y1) clr_y1 = image->dst_y + image->h; uint32_t *lfb = fb->getFrameBufferPointer() + image->dst_x + xres * image->dst_y; unsigned char *bm = image->bitmap; int bm_add = image->stride - image->w; int lfb_add = xres - image->w; for (int y = 0; y < image->h; y++) { for (int x = 0; x < image->w; x++) { if (*bm) *lfb = colortable[*bm]; lfb++, bm++; } lfb += lfb_add; bm += bm_add; } } image = image->next; } fb->getInstance()->blit(); } continue; } else { if (clr_x1 && clr_y1) {
/***************************************************************************** * Create: Open libass decoder. *****************************************************************************/ static int Create( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t *)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_SSA ) return VLC_EGENERIC; p_dec->pf_decode_sub = DecodeBlock; p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; /* */ vlc_mutex_init( &p_sys->lock ); p_sys->i_refcount = 1; memset( &p_sys->fmt, 0, sizeof(p_sys->fmt) ); p_sys->i_max_stop = VLC_TS_INVALID; p_sys->p_library = NULL; p_sys->p_renderer = NULL; p_sys->p_track = NULL; /* Create libass library */ ASS_Library *p_library = p_sys->p_library = ass_library_init(); if( !p_library ) { msg_Warn( p_dec, "Libass library creation failed" ); DecSysRelease( p_sys ); return VLC_EGENERIC; } /* load attachments */ input_attachment_t **pp_attachments; int i_attachments; if( decoder_GetInputAttachments( p_dec, &pp_attachments, &i_attachments )) { i_attachments = 0; pp_attachments = NULL; } for( int k = 0; k < i_attachments; k++ ) { input_attachment_t *p_attach = pp_attachments[k]; bool found = false; /* Check mimetype*/ if( !strcasecmp( p_attach->psz_mime, "application/x-truetype-font" ) ) found = true; /* Then extension */ else if( !found && strlen( p_attach->psz_name ) > 4 ) { char *ext = p_attach->psz_name + strlen( p_attach->psz_name ) - 4; if( !strcasecmp( ext, ".ttf" ) || !strcasecmp( ext, ".otf" ) || !strcasecmp( ext, ".ttc" ) ) found = true; } if( found ) { msg_Dbg( p_dec, "adding embedded font %s", p_attach->psz_name ); ass_add_font( p_sys->p_library, p_attach->psz_name, p_attach->p_data, p_attach->i_data ); } vlc_input_attachment_Delete( p_attach ); } free( pp_attachments ); ass_set_extract_fonts( p_library, true ); ass_set_style_overrides( p_library, NULL ); /* Create the renderer */ ASS_Renderer *p_renderer = p_sys->p_renderer = ass_renderer_init( p_library ); if( !p_renderer ) { msg_Warn( p_dec, "Libass renderer creation failed" ); DecSysRelease( p_sys ); return VLC_EGENERIC; } ass_set_use_margins( p_renderer, false); //if( false ) // ass_set_margins( p_renderer, int t, int b, int l, int r); ass_set_hinting( p_renderer, ASS_HINTING_LIGHT ); ass_set_font_scale( p_renderer, 1.0 ); ass_set_line_spacing( p_renderer, 0.0 ); #if defined( __ANDROID__ ) const char *psz_font = "/system/fonts/DroidSans-Bold.ttf"; const char *psz_family = "Droid Sans Bold"; #elif defined (__APPLE__) #if !TARGET_OS_IPHONE const char *psz_font = NULL; /* We don't ship a default font with VLC */ const char *psz_family = "Arial"; /* Use Arial if we can't find anything more suitable */ #else CFURLRef fileURL; fileURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("OpenSans-Regular.ttf"), NULL, NULL); if (!fileURL) return VLC_EGENERIC; CFStringRef urlString = CFURLCopyFileSystemPath(fileURL, kCFURLPOSIXPathStyle); CFRelease(fileURL); if (!urlString) return VLC_EGENERIC; CFIndex length = CFStringGetLength(urlString); if (!length) return VLC_EGENERIC; length++; char *psz_path = (char *)malloc(length); CFStringGetCString(urlString, psz_path, length, kCFStringEncodingUTF8); CFRelease(urlString); const char *psz_font = (const char *)strdup(psz_path); free(psz_path); const char *psz_family = "Open Sans"; #endif #else const char *psz_font = NULL; /* We don't ship a default font with VLC */ const char *psz_family = "Arial"; /* Use Arial if we can't find anything more suitable */ #endif #ifdef HAVE_FONTCONFIG #if defined(_WIN32) || defined(__APPLE__) dialog_progress_bar_t *p_dialog = dialog_ProgressCreate( p_dec, _("Building font cache"), _( "Please wait while your font cache is rebuilt.\n" "This should take less than a minute." ), NULL ); #endif ass_set_fonts( p_renderer, psz_font, psz_family, true, NULL, 1 ); // setup default font/family #if defined(_WIN32) || defined(__APPLE__) if( p_dialog ) { dialog_ProgressSet( p_dialog, NULL, 1.0 ); dialog_ProgressDestroy( p_dialog ); } #endif #else /* FIXME you HAVE to give him a font if no fontconfig */ ass_set_fonts( p_renderer, psz_font, psz_family, false, NULL, 1 ); #endif /* Add a track */ ASS_Track *p_track = p_sys->p_track = ass_new_track( p_sys->p_library ); if( !p_track ) { DecSysRelease( p_sys ); return VLC_EGENERIC; } ass_process_codec_private( p_track, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); p_dec->fmt_out.i_cat = SPU_ES; p_dec->fmt_out.i_codec = VLC_CODEC_RGBA; return VLC_SUCCESS; }