From 12895f2786b4fb4dac2271168b30029b650fb620 Mon Sep 17 00:00:00 2001 From: hizzlekizzle Date: Thu, 1 Jan 2026 17:22:31 -0600 Subject: [PATCH] [ffmpeg-libretro] fix softsubs --- cores/libretro-ffmpeg/ffmpeg_core.c | 45 +++++++++++++++++++---------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/cores/libretro-ffmpeg/ffmpeg_core.c b/cores/libretro-ffmpeg/ffmpeg_core.c index 051b5e3e4aee..d5b36909ec48 100644 --- a/cores/libretro-ffmpeg/ffmpeg_core.c +++ b/cores/libretro-ffmpeg/ffmpeg_core.c @@ -130,6 +130,7 @@ static ASS_Track *ass_track[MAX_STREAMS]; static uint8_t *ass_extra_data[MAX_STREAMS]; static size_t ass_extra_data_size[MAX_STREAMS]; static slock_t *ass_lock; +static void render_ass_img(AVFrame *conv_frame, ASS_Image *img); #endif struct attachment @@ -839,6 +840,19 @@ void CORE_PREFIX(retro_run)(void) video_buffer_get_finished_slot(video_buffer, &ctx); pts = ctx->pts; +#ifdef HAVE_SSA + double video_time = ctx->pts * av_q2d(fctx->streams[video_stream_index]->time_base); + slock_lock(ass_lock); + if (ass_render && ctx->ass_track_active) + { + int change = 0; + ASS_Image *img = ass_render_frame(ass_render, ctx->ass_track_active, + 1000 * video_time, &change); + render_ass_img(ctx->target, img); + } + slock_unlock(ass_lock); +#endif + #ifdef HAVE_OPENGLES data = video_frame_temp_buffer; #else @@ -859,6 +873,7 @@ void CORE_PREFIX(retro_run)(void) #ifndef HAVE_OPENGLES glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); #endif + glBindTexture(GL_TEXTURE_2D, frames[1].tex); #if defined(HAVE_OPENGLES) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, @@ -1495,19 +1510,6 @@ static void sws_worker_thread(void *arg) ctx->pts = ctx->source->best_effort_timestamp; -#ifdef HAVE_SSA - double video_time = ctx->pts * av_q2d(fctx->streams[video_stream_index]->time_base); - slock_lock(ass_lock); - if (ass_render && ctx->ass_track_active) - { - int change = 0; - ASS_Image *img = ass_render_frame(ass_render, ctx->ass_track_active, - 1000 * video_time, &change); - render_ass_img(ctx->target, img); - } - slock_unlock(ass_lock); -#endif - av_frame_unref(ctx->source); #if ENABLE_HW_ACCEL av_frame_unref(ctx->hw_source); @@ -1910,13 +1912,26 @@ static void decode_thread(void *data) break; } } + log_cb(RETRO_LOG_DEBUG, "[FFMPEG] [ASS] Decoded subtitle packet, num_rects=%d, pkt->pts=%lld, pkt->duration=%lld, sub.start=%u, sub.end=%u\n", + sub.num_rects, (long long)pkt->pts, (long long)pkt->duration, sub.start_display_time, sub.end_display_time); #ifdef HAVE_SSA for (i = 0; i < sub.num_rects; i++) { slock_lock(ass_lock); + ass_flush_events(ass_track_active); if (sub.rects[i]->ass && ass_track_active) - ass_process_data(ass_track_active, - sub.rects[i]->ass, strlen(sub.rects[i]->ass)); + { + char dialogue_line[4096]; + + /* Convert packet timing from stream timebase to milliseconds */ + double timebase_ms = av_q2d(fctx->streams[subtitle_stream]->time_base) * 1000.0; + long long start_time = (long long)((pkt->pts >= 0 ? pkt->pts : 0) * timebase_ms) + sub.start_display_time; + long long duration = (long long)(pkt->duration > 0 ? (pkt->duration * timebase_ms) : (sub.end_display_time - sub.start_display_time)); + + snprintf(dialogue_line, sizeof(dialogue_line), "Dialogue: %s", sub.rects[i]->ass); + + ass_process_chunk(ass_track_active, dialogue_line, strlen(dialogue_line), start_time, duration); + } slock_unlock(ass_lock); } #endif