avcodec/libaribcaption: handle skipped ruby in ass single rect mode

With ass_single_rect=1 and ignore_ruby=1, a caption whose regions are
all ruby still produced one event holding only the position tags, even
without a clear screen (CS). Track whether any region was written and
treat "none" like the multi rect mode: emit nothing, or the empty clear
event if the caption carries CS.

The line separator was also appended after every region but the last
one, so skipping a trailing ruby region left a dangling "{\r}\N". Write
it before every written region but the first instead. Output is
unchanged when no region is skipped.

The position of the single rect was also taken from all regions,
including skipped ruby above the text. Ignore skipped regions there too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DdDiDRusmi6eD7qSrKBjHb
This commit is contained in:
Ruk DoeandClaude Opus 5.5 authored and michaelni committed 2026-11-06 04:39:07 +00:00
1 parent 4ec127c826
commit b86ace6719
1 file changed
+12 -8
+12 -8
View File
@@ -587,6 +587,7 @@ static int aribcaption_trans_ass_subtitle(ARIBCaptionContext *ctx)
AVSubtitle *sub = ctx->sub;
AVBPrint buf;
bool single_rect = ctx->ass_single_rect;
bool emitted = false;
int ret = 0, rect_idx;
if (ctx->caption.plane_width > 0 && ctx->caption.plane_height > 0 &&
@@ -623,6 +624,8 @@ static int aribcaption_trans_ass_subtitle(ARIBCaptionContext *ctx)
x = ctx->plane_width;
y = ctx->plane_height;
for (int i = 0; i < ctx->caption.region_count; i++) {
if (ctx->caption.regions[i].is_ruby && ctx->ignore_ruby)
continue;
rx = ctx->caption.regions[i].x;
ry = ctx->caption.regions[i].y;
if (rx < x)
@@ -654,6 +657,10 @@ static int aribcaption_trans_ass_subtitle(ARIBCaptionContext *ctx)
if (region->is_ruby && ctx->ignore_ruby)
continue;
if (single_rect && emitted)
av_bprintf(&buf, "{\\r}\\N");
emitted = true;
if (!single_rect) {
int x = region->x;
int y = region->y;
@@ -744,12 +751,9 @@ static int aribcaption_trans_ass_subtitle(ARIBCaptionContext *ctx)
}
if (single_rect) {
if (i + 1 < ctx->caption.region_count)
av_bprintf(&buf, "{\\r}\\N");
ff_dlog(ctx, "ASS subtitle%s (%d,%d) %dx%d [%d]\n",
ff_dlog(ctx, "ASS subtitle%s (%d,%d) %dx%d [region %d]\n",
(region->is_ruby) ? " (ruby)" : "",
region->x, region->y, region->width, region->height,
rect_idx);
region->x, region->y, region->width, region->height, i);
} else {
if (!av_bprint_is_complete(&buf)) {
ret = AVERROR(ENOMEM);
@@ -766,9 +770,9 @@ static int aribcaption_trans_ass_subtitle(ARIBCaptionContext *ctx)
rect_idx++;
}
}
if (!single_rect && !rect_idx) {
/* Every region was skipped as ruby. A clear screen (CS) must still
erase the previous caption. */
if (!emitted) {
/* Every region was skipped as ruby. Emit nothing, but a clear
screen (CS) must still erase the previous caption. */
av_bprint_finalize(&buf, NULL);
if (!(ctx->caption.flags & ARIBCC_CAPTIONFLAGS_CLEARSCREEN))
return 0;