[FFmpeg-devel] [PATCH 02/10] libavcodec/ccaption_dec: fix timestamps on generated subtitles by buffering after EOC/newline commands
Aman Gupta
ffmpeg at tmm1.net
Wed Jan 6 08:41:34 CET 2016
From: Aman Gupta <aman at tmm1.net>
before:
Dialogue: 0,0:00:00.03,0:00:00.67,Default,,0,0,0,,EVERYBODY, TONIGHT WE'LL COVER
Dialogue: 0,0:00:00.67,0:00:02.30,Default,,0,0,0,,EVERYBODY, TONIGHT WE'LL COVER\NTHE NEWS WE MISSED OVER THE
Dialogue: 0,0:00:02.30,0:00:03.57,Default,,0,0,0,,THE NEWS WE MISSED OVER THE\NHOLIDAYS AND SEE HOW THE
after:
Dialogue: 0,0:00:00.67,0:00:02.30,Default,,0,0,0,,EVERYBODY, TONIGHT WE'LL COVER
Dialogue: 0,0:00:02.30,0:00:03.57,Default,,0,0,0,,EVERYBODY, TONIGHT WE'LL COVER\NTHE NEWS WE MISSED OVER THE
Dialogue: 0,0:00:03.57,0:00:04.30,Default,,0,0,0,,THE NEWS WE MISSED OVER THE\NHOLIDAYS AND SEE HOW THE
---
libavcodec/ccaption_dec.c | 47 ++++++++++++++++++++++++-----------------------
1 file changed, 24 insertions(+), 23 deletions(-)
diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c
index 12e8f1d..f651c88 100644
--- a/libavcodec/ccaption_dec.c
+++ b/libavcodec/ccaption_dec.c
@@ -160,10 +160,8 @@ typedef struct CCaptionSubContext {
int screen_changed;
int rollup;
enum cc_mode mode;
- int64_t start_time;
- /* visible screen time */
- int64_t startv_time;
- int64_t end_time;
+ char *prev_string;
+ int64_t prev_time;
char prev_cmd[2];
/* buffer to store pkt data */
AVBufferRef *pktbuf;
@@ -310,12 +308,11 @@ static void roll_up(CCaptionSubContext *ctx)
UNSET_FLAG(screen->row_used, ctx->cursor_row);
}
-static int reap_screen(CCaptionSubContext *ctx, int64_t pts)
+static int reap_screen(CCaptionSubContext *ctx)
{
int i;
int ret = 0;
struct Screen *screen = ctx->screen + ctx->active_screen;
- ctx->start_time = ctx->startv_time;
av_bprint_clear(&ctx->buffer);
for (i = 0; screen->row_used && i < SCREEN_ROWS; i++)
@@ -341,8 +338,6 @@ static int reap_screen(CCaptionSubContext *ctx, int64_t pts)
ctx->screen_changed = 1;
}
- ctx->startv_time = pts;
- ctx->end_time = pts;
return ret;
}
@@ -401,9 +396,9 @@ static void handle_erase(CCaptionSubContext *ctx, int n_screen)
screen->row_used = 0;
}
-static void handle_eoc(CCaptionSubContext *ctx, int64_t pts)
+static void handle_eoc(CCaptionSubContext *ctx)
{
- reap_screen(ctx, pts);
+ reap_screen(ctx);
ctx->active_screen = !ctx->active_screen;
ctx->cursor_column = 0;
}
@@ -415,7 +410,7 @@ static void handle_delete_end_of_row(CCaptionSubContext *ctx, char hi, char lo)
write_char(ctx, row, ctx->cursor_column, 0);
}
-static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
+static void handle_char(CCaptionSubContext *ctx, char hi, char lo)
{
struct Screen *screen = get_writing_screen(ctx);
char *row = screen->characters[ctx->cursor_row];
@@ -443,7 +438,7 @@ static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
ff_dlog(ctx, "(%c)\n", hi);
}
-static void process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint8_t lo)
+static void process_cc608(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
{
if (hi == ctx->prev_cmd[0] && lo == ctx->prev_cmd[1]) {
/* ignore redundant command */
@@ -489,7 +484,7 @@ static void process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint
case 0x2d:
/* carriage return */
ff_dlog(ctx, "carriage return\n");
- reap_screen(ctx, pts);
+ reap_screen(ctx);
roll_up(ctx);
ctx->cursor_column = 0;
break;
@@ -500,7 +495,7 @@ static void process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint
case 0x2f:
/* end of caption */
ff_dlog(ctx, "handle_eoc\n");
- handle_eoc(ctx, pts);
+ handle_eoc(ctx);
break;
default:
ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
@@ -510,7 +505,7 @@ static void process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint
/* ignore tab offset */
} else if (hi >= 0x20) {
/* Standard characters (always in pairs) */
- handle_char(ctx, hi, lo, pts);
+ handle_char(ctx, hi, lo);
} else {
/* Ignoring all other non data code */
ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
@@ -549,16 +544,22 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp
if(cc_type == 1)
continue;
else
- process_cc608(ctx, avpkt->pts, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f);
+ process_cc608(ctx, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f);
if (ctx->screen_changed)
{
- int start_time = av_rescale_q(ctx->start_time, avctx->time_base, (AVRational){ 1, 100 });
- int end_time = av_rescale_q(ctx->end_time, avctx->time_base, (AVRational){ 1, 100 });
- ff_dlog(ctx, "cdp writing data (%s)\n",ctx->buffer.str);
- ret = ff_ass_add_rect_bprint(sub, &ctx->buffer, start_time, end_time - start_time);
- if (ret < 0)
- return ret;
- sub->pts = av_rescale_q(ctx->start_time, avctx->time_base, AV_TIME_BASE_Q);
+ if (ctx->prev_string) {
+ int start_time = av_rescale_q(ctx->prev_time, avctx->time_base, (AVRational){ 1, 100 });
+ int end_time = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){ 1, 100 });
+ ret = ff_ass_add_rect(sub, ctx->prev_string, start_time, end_time - start_time, 0);
+ if (ret < 0)
+ return ret;
+ sub->pts = av_rescale_q(ctx->prev_time, avctx->time_base, AV_TIME_BASE_Q);
+ av_freep(&ctx->prev_string);
+ }
+
+ av_bprintf(&ctx->buffer, "\r\n");
+ ctx->prev_string = av_strdup(ctx->buffer.str);
+ ctx->prev_time = avpkt->pts;
ctx->screen_changed = 0;
}
}
--
2.5.3
More information about the ffmpeg-devel
mailing list