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 || ass_force_reload) { 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 + ass_top_margin, res->mb + ass_bottom_margin, res->ml, res->mr); ass_set_aspect_ratio(ass_renderer, dar, (double)res->srcw / res->srch); src->initialized = 1; ass_force_reload = 0; } aimg = sub_visibility && ass_track && ts != MP_NOPTS_VALUE ? ass_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; }
void loop() { int dif = 0; ASS_Image *img = ass_render_frame(ass_renderer, track, (int) (tm * 1000), &dif); tm += 1 / fps; if(dif == 0) return; SDL_RenderClear( renderer ); while (img) { SDL_Surface* surface = SDL_CreateRGBSurface (0, img->w, img->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); blend_single(surface, img); SDL_Rect dest = { img->dst_x, img->dst_y, img->w, img->h }; SDL_Texture *tex = SDL_CreateTextureFromSurface(renderer, surface); SDL_RenderCopy(renderer, tex, NULL, &dest); SDL_DestroyTexture (tex); SDL_FreeSurface (surface); //free(img->bitmap); img = img->next; //count++; } //free(img); SDL_RenderPresent( renderer ); SDL_Delay(10); }
int main(int argc, char *argv[]) { const int frame_w = 640; const int frame_h = 480; 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); init(frame_w, frame_h); ASS_Track *track = ass_read_file(ass_library, subfile, NULL); if (!track) { printf("track init failed!\n"); return 1; } ASS_Image *img = ass_render_frame(ass_renderer, track, (int) (tm * 1000), NULL); image_t *frame = gen_image(frame_w, frame_h); blend(frame, img); ass_free_track(track); ass_renderer_done(ass_renderer); ass_library_done(ass_library); write_png(imgfile, frame); return 0; }
void mp_ass_render_frame(ASS_Renderer *renderer, ASS_Track *track, double time, struct sub_bitmap **parts, struct sub_bitmaps *res) { int changed; ASS_Image *imgs = ass_render_frame(renderer, track, time, &changed); if (changed == 2) res->bitmap_id = ++res->bitmap_pos_id; else if (changed) res->bitmap_pos_id++; res->format = SUBBITMAP_LIBASS; res->parts = *parts; res->num_parts = 0; int num_parts_alloc = MP_TALLOC_ELEMS(res->parts); for (struct ass_image *img = imgs; img; img = img->next) { if (img->w == 0 || img->h == 0) continue; if (res->num_parts >= num_parts_alloc) { num_parts_alloc = FFMAX(num_parts_alloc * 2, 32); res->parts = talloc_realloc(NULL, res->parts, struct sub_bitmap, num_parts_alloc); } struct sub_bitmap *p = &res->parts[res->num_parts]; p->bitmap = img->bitmap; p->stride = img->stride; p->libass.color = img->color; p->dw = p->w = img->w; p->dh = p->h = img->h; p->x = img->dst_x; p->y = img->dst_y; res->num_parts++; }
void BigPotSubtitleAss::show(int time) { int a; _img = ass_render_frame(_ren, _track, time, &a); //cout << engine_->getTicks() << endl; auto img = _img; if (a) { destroyAllTex(); while (img) { auto t = engine_->transBitmapToTexture(img->bitmap, img->color, img->w, img->h, img->stride); engine_->renderCopy(t, img->dst_x, img->dst_y, img->w, img->h, 1); _tex_v.push_back(t); img = img->next; } } else { int i = 0; while (img && i < _tex_v.size()) { engine_->renderCopy(_tex_v[i++], img->dst_x, img->dst_y, img->w, img->h, 1); img = img->next; } } //cout << engine_->getTicks() << endl; }
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); }
/// @brief Draw subtitles /// @param frame /// @param time /// @return /// void LibassSubtitlesProvider::DrawSubtitles(AegiVideoFrame &frame,double time) { // Set size ass_set_frame_size(ass_renderer, frame.w, frame.h); // Get frame ASS_Image* img = ass_render_frame(ass_renderer, ass_track, int(time * 1000), NULL); // libass actually returns several alpha-masked monochrome images. // Here, we loop through their linked list, get the colour of the current, and blend into the frame. // This is repeated for all of them. while (img) { // Get colours unsigned int opacity = 255 - ((unsigned int)_a(img->color)); unsigned int r = (unsigned int)_r(img->color); unsigned int g = (unsigned int)_g(img->color); unsigned int b = (unsigned int) _b(img->color); // Prepare copy int src_stride = img->stride; int dst_stride = frame.pitch; const unsigned char *src = img->bitmap; unsigned char *dst = frame.data; if (frame.flipped) { dst += dst_stride * (frame.h - 1); dst_stride *= -1; } dst += (img->dst_y * dst_stride + img->dst_x * 4); // Copy image to destination frame for (int y = 0; y < img->h; y++) { unsigned char *dstp = dst; for (int x = 0; x < img->w; ++x) { unsigned int k = ((unsigned)src[x]) * opacity / 255; unsigned int ck = 255 - k; *dstp = (k * b + ck * *dstp) / 255; ++dstp; *dstp = (k * g + ck * *dstp) / 255; ++dstp; *dstp = (k * r + ck * *dstp) / 255; ++dstp; ++dstp; } dst += dst_stride; src += src_stride; } // Next image img = img->next; } }
static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, int format, double pts, struct sub_bitmaps *res) { struct sd_ass_priv *ctx = sd->priv; struct MPOpts *opts = sd->opts; bool no_ass = !opts->ass_enabled || ctx->on_top || opts->ass_style_override == 5; bool converted = ctx->is_converted || no_ass; ASS_Track *track = no_ass ? ctx->shadow_track : ctx->ass_track; ASS_Renderer *renderer = ctx->ass_renderer; if (pts == MP_NOPTS_VALUE || !renderer) return; double scale = dim.display_par; if (!converted && (!opts->ass_style_override || opts->ass_vsfilter_aspect_compat)) { // Let's use the original video PAR for vsfilter compatibility: double par = ctx->video_params.p_w / (double)ctx->video_params.p_h; if (isnormal(par)) scale *= par; } configure_ass(sd, &dim, converted, track); ass_set_pixel_aspect(renderer, scale); if (!converted && (!opts->ass_style_override || opts->ass_vsfilter_blur_compat)) { ass_set_storage_size(renderer, ctx->video_params.w, ctx->video_params.h); } else { ass_set_storage_size(renderer, 0, 0); } long long ts = find_timestamp(sd, pts); if (ctx->duration_unknown && pts != MP_NOPTS_VALUE) { mp_ass_flush_old_events(track, ts); ctx->num_seen_packets = 0; sd->preload_ok = false; } if (no_ass) fill_plaintext(sd, pts); int changed; ASS_Image *imgs = ass_render_frame(renderer, track, ts, &changed); mp_ass_packer_pack(ctx->packer, &imgs, 1, changed, format, res); if (!converted && res->num_parts > 0) { // mangle_colors() modifies the color field, so copy the thing. MP_TARRAY_GROW(ctx, ctx->bs, res->num_parts); memcpy(ctx->bs, res->parts, sizeof(ctx->bs[0]) * res->num_parts); res->parts = ctx->bs; mangle_colors(sd, res); } }
void csri_render(csri_inst *inst, struct csri_frame *frame, double time) { ass_image_t *img = ass_render_frame(inst->ass_renderer, inst->ass_track, (int)(time * 1000), NULL); while (img) { unsigned bpp, alpha = 256 - (img->color && 0xFF); int src_d, dst_d; unsigned char *src, *dst, *endy, *endx; unsigned char c[3] = { (img->color >> 8) & 0xFF, /* B */ (img->color >> 16) & 0xFF, /* G */ img->color >> 24 /* R */ }; if ((frame->pixfmt | 1) == CSRI_F__RGB || frame->pixfmt == CSRI_F_RGB) { unsigned char tmp = c[2]; c[2] = c[0]; c[0] = tmp; } bpp = frame->pixfmt >= 0x200 ? 3 : 4; dst = frame->planes[0] + img->dst_y * frame->strides[0] + img->dst_x * bpp; if (frame->pixfmt & 1) dst++; src = img->bitmap; src_d = img->stride - img->w; dst_d = frame->strides[0] - img->w * bpp; endy = src + img->h * img->stride; while (src != endy) { endx = src + img->w; while (src != endx) { /* src[x]: 0..255, alpha: 1..256 (see above) * -> src[x]*alpha: 0<<8..255<<8 * -> need 1..256 for mult => +1 */ unsigned s = ((*src++ * alpha) >> 8) + 1; unsigned d = 257 - s; /* c[0]: 0.255, s/d: 1..256 */ dst[0] = (s*c[0] + d*dst[0]) >> 8; dst[1] = (s*c[1] + d*dst[1]) >> 8; dst[2] = (s*c[2] + d*dst[2]) >> 8; dst += bpp; } dst += dst_d; src += src_d; } img = img->next; } }
static int SubpictureValidate( subpicture_t *p_subpic, bool b_fmt_src, const video_format_t *p_fmt_src, bool b_fmt_dst, const video_format_t *p_fmt_dst, mtime_t i_ts ) { decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys; ass_handle_t *p_ass = p_sys->p_ass; vlc_mutex_lock( &libass_lock ); /* FIXME why this mix of src/dst */ video_format_t fmt = *p_fmt_dst; fmt.i_chroma = VLC_CODEC_RGBA; fmt.i_bits_per_pixel = 0; fmt.i_width = fmt.i_visible_width = p_fmt_src->i_width; fmt.i_height = fmt.i_visible_height = p_fmt_src->i_height; fmt.i_x_offset = fmt.i_y_offset = 0; if( b_fmt_src || b_fmt_dst ) { ass_set_frame_size( p_ass->p_renderer, fmt.i_width, fmt.i_height ); #if defined( LIBASS_VERSION ) && LIBASS_VERSION >= 0x00907000 ass_set_aspect_ratio( p_ass->p_renderer, 1.0, 1.0 ); // TODO ? #else ass_set_aspect_ratio( p_ass->p_renderer, 1.0 ); // TODO ? #endif p_ass->fmt = fmt; } /* */ const mtime_t i_stream_date = p_subpic->updater.p_sys->i_pts + (i_ts - p_subpic->i_start); int i_changed; ASS_Image *p_img = ass_render_frame( p_ass->p_renderer, p_sys->p_track, i_stream_date/1000, &i_changed ); if( !i_changed && !b_fmt_src && !b_fmt_dst && (p_img != NULL) == (p_subpic->p_region != NULL) ) { vlc_mutex_unlock( &libass_lock ); return VLC_SUCCESS; } p_subpic->updater.p_sys->p_img = p_img; /* The lock is released by SubpictureUpdate */ return VLC_EGENERIC; }
QImage SubtitleProcessorLibASS::getImage(qreal pts, QRect *boundingRect) { if (!ass::api::loaded()) return QImage(); if (!m_ass) { qWarning("ass library not available"); return QImage(); } if (!m_renderer) { qWarning("ass renderer not available"); return QImage(); } if (!m_track) { qWarning("ass track not available"); return QImage(); } int detect_change = 0; ASS_Image *img = ass_render_frame(m_renderer, m_track, (long long)(pts * 1000.0), &detect_change); if (!detect_change) { if (boundingRect) *boundingRect = m_bound; return m_image; } QRect rect(0, 0, 0, 0); ASS_Image *i = img; while (i) { rect |= QRect(i->dst_x, i->dst_y, i->w, i->h); i = i->next; } m_bound = rect; if (boundingRect) { *boundingRect = m_bound; } QImage image(rect.size(), QImage::Format_ARGB32); image.fill(Qt::transparent); i = img; while (i) { if (i->w <= 0 || i->h <= 0) { i = i->next; continue; } renderASS32(&image, i, i->dst_x - rect.x(), i->dst_y - rect.y()); i = i->next; } m_image = image; return image; }
static int filter_frame(AVFilterLink *inlink, AVFrame *picref) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AssContext *ass = ctx->priv; int detect_change = 0; double time_ms = picref->pts * av_q2d(inlink->time_base) * 1000; ASS_Image *image = ass_render_frame(ass->renderer, ass->track, time_ms, &detect_change); if (detect_change) av_log(ctx, AV_LOG_DEBUG, "Change happened at time ms:%f\n", time_ms); overlay_ass_image(ass, picref, image); return ff_filter_frame(outlink, picref); }
static const VSFrameRef *VS_CC assGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { AssData *d = (AssData *) * instanceData; if(n != d->lastn) { ASS_Image *img; int64_t ts = 0; int changed; if(d->file != NULL) ts = (int64_t)n * 1000 * d->vi[0].fpsDen / d->vi[0].fpsNum; img = ass_render_frame(d->ass_renderer, d->ass, ts, &changed); if (changed) { VSFrameRef *dst = vsapi->newVideoFrame(d->vi[0].format, d->vi[0].width, d->vi[0].height, NULL, core); VSFrameRef *a = vsapi->newVideoFrame(d->vi[1].format, d->vi[1].width, d->vi[1].height, NULL, core); assRender(dst, a, vsapi, img); vsapi->freeFrame(d->lastframe); vsapi->freeFrame(d->lastalpha); d->lastframe = dst; d->lastalpha = a; } d->lastn = n; } if(vsapi->getOutputIndex(frameCtx) == 0) return vsapi->cloneFrameRef(d->lastframe); else return vsapi->cloneFrameRef(d->lastalpha); }
static int SubpictureValidate( subpicture_t *p_subpic, bool b_fmt_src, const video_format_t *p_fmt_src, bool b_fmt_dst, const video_format_t *p_fmt_dst, mtime_t i_ts ) { decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys; vlc_mutex_lock( &p_sys->lock ); video_format_t fmt = *p_fmt_dst; fmt.i_chroma = VLC_CODEC_RGBA; fmt.i_bits_per_pixel = 0; fmt.i_visible_width = fmt.i_width; fmt.i_visible_height = fmt.i_height; fmt.i_x_offset = 0; fmt.i_y_offset = 0; if( b_fmt_src || b_fmt_dst ) { ass_set_frame_size( p_sys->p_renderer, fmt.i_width, fmt.i_height ); const double src_ratio = (double)p_fmt_src->i_width / p_fmt_src->i_height; const double dst_ratio = (double)p_fmt_dst->i_width / p_fmt_dst->i_height; ass_set_aspect_ratio( p_sys->p_renderer, dst_ratio / src_ratio, 1 ); p_sys->fmt = fmt; } /* */ const mtime_t i_stream_date = p_subpic->updater.p_sys->i_pts + (i_ts - p_subpic->i_start); int i_changed; ASS_Image *p_img = ass_render_frame( p_sys->p_renderer, p_sys->p_track, i_stream_date/1000, &i_changed ); if( !i_changed && !b_fmt_src && !b_fmt_dst && (p_img != NULL) == (p_subpic->p_region != NULL) ) { vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; } p_subpic->updater.p_sys->p_img = p_img; /* The lock is released by SubpictureUpdate */ return VLC_EGENERIC; }
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); }
bool LibASS::getOSD(QMPlay2_OSD *&osd, const QByteArray &txt, double duration) { if (!osd_track || !osd_style || !osd_event || !osd_renderer || !W || !H) return false; osd_track->PlayResX = W; osd_track->PlayResY = H; ass_set_frame_size(osd_renderer, W, H); osd_event->Text = (char *)txt.data(); int ch; ASS_Image *img = ass_render_frame(osd_renderer, osd_track, 0, &ch); osd_event->Text = NULL; if (!img) return false; bool old_osd = osd; if (!old_osd) osd = new QMPlay2_OSD; else { osd->lock(); if (ch) osd->clear(); } osd->setText(txt); osd->setDuration(duration); if (ch || !old_osd) { addImgs(img, osd); osd->genChecksum(); } if (old_osd) osd->unlock(); osd->start(); return true; }
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) {
bool LibASS::getASS(QMPlay2_OSD *&osd, double pos) { if (!ass_sub_track || !ass_sub_renderer || !W || !H) return false; int playResX = ass_sub_track->PlayResX; int playResY = ass_sub_track->PlayResY; if (overridePlayRes) { ass_sub_track->PlayResX = 384; ass_sub_track->PlayResY = 288; } double _fontScale = fontScale; if (_fontScale != 1.0) { for (int i = 0; i < ass_sub_track->n_styles; i++) { ass_sub_track->styles[i].ScaleX *= _fontScale; ass_sub_track->styles[i].ScaleY *= _fontScale; ass_sub_track->styles[i].Shadow *= _fontScale; ass_sub_track->styles[i].Outline *= _fontScale; } } ass_set_frame_size(ass_sub_renderer, W, H); int ch; ASS_Image *img = ass_render_frame(ass_sub_renderer, ass_sub_track, pos * 1000, &ch); if (_fontScale != 1.0) { for (int i = 0; i < ass_sub_track->n_styles; i++) { ass_sub_track->styles[i].ScaleX /= _fontScale; ass_sub_track->styles[i].ScaleY /= _fontScale; ass_sub_track->styles[i].Shadow /= _fontScale; ass_sub_track->styles[i].Outline /= _fontScale; } } if (overridePlayRes) { ass_sub_track->PlayResX = playResX; ass_sub_track->PlayResY = playResY; } if (!img) return false; bool old_osd = osd; if (!old_osd) osd = new QMPlay2_OSD; else { osd->lock(); if (ch) osd->clear(false); } osd->setPTS(pos); if (ch || !old_osd) { addImgs(img, osd); osd->genChecksum(); } if (old_osd) osd->unlock(); return true; }
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; }
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; }