From 4b1c9b720e11d200ca7090210b34c409f43fafeb Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Mon, 25 Nov 2013 16:27:41 +0100 Subject: [PATCH] lavc/srtenc: use bprint for text buffers. Fix trac ticket #3120. --- libavcodec/srtenc.c | 48 ++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/libavcodec/srtenc.c b/libavcodec/srtenc.c index 3036a7fb0c..89c26dcbf0 100644 --- a/libavcodec/srtenc.c +++ b/libavcodec/srtenc.c @@ -22,6 +22,7 @@ #include #include "avcodec.h" #include "libavutil/avstring.h" +#include "libavutil/bprint.h" #include "ass_split.h" #include "ass.h" @@ -31,10 +32,8 @@ typedef struct { AVCodecContext *avctx; ASSSplitContext *ass_ctx; - char buffer[2048]; - char *ptr; - char *end; - char *dialog_start; + AVBPrint buffer; + unsigned timestamp_end; int count; char stack[SRT_STACK_SIZE]; int stack_ptr; @@ -49,7 +48,7 @@ static void srt_print(SRTContext *s, const char *str, ...) { va_list vargs; va_start(vargs, str); - s->ptr += vsnprintf(s->ptr, s->end - s->ptr, str, vargs); + av_vbprintf(&s->buffer, str, vargs); va_end(vargs); } @@ -138,14 +137,14 @@ static av_cold int srt_encode_init(AVCodecContext *avctx) SRTContext *s = avctx->priv_data; s->avctx = avctx; s->ass_ctx = ff_ass_split(avctx->subtitle_header); + av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; } static void srt_text_cb(void *priv, const char *text, int len) { SRTContext *s = priv; - av_strlcpy(s->ptr, text, FFMIN(s->end-s->ptr, len+1)); - s->ptr += len; + av_bprint_append_data(&s->buffer, text, len); } static void srt_new_line_cb(void *priv, int forced) @@ -208,11 +207,19 @@ static void srt_move_cb(void *priv, int x1, int y1, int x2, int y2, char buffer[32]; int len = snprintf(buffer, sizeof(buffer), " X1:%03u X2:%03u Y1:%03u Y2:%03u", x1, x2, y1, y2); - if (s->end - s->ptr > len) { - memmove(s->dialog_start+len, s->dialog_start, s->ptr-s->dialog_start+1); - memcpy(s->dialog_start, buffer, len); - s->ptr += len; + unsigned char *dummy; + unsigned room; + + av_bprint_get_buffer(&s->buffer, len, &dummy, &room); + if (room >= len) { + memmove(s->buffer.str + s->timestamp_end + len, + s->buffer.str + s->timestamp_end, + s->buffer.len - s->timestamp_end + 1); + memcpy(s->buffer.str + s->timestamp_end, buffer, len); } + /* Increment even if av_bprint_get_buffer() did not return enough room: + the bprint structure will be treated as truncated. */ + s->buffer.len += len; } } @@ -243,10 +250,9 @@ static int srt_encode_frame(AVCodecContext *avctx, { SRTContext *s = avctx->priv_data; ASSDialog *dialog; - int i, len, num; + int i, num; - s->ptr = s->buffer; - s->end = s->ptr + sizeof(s->buffer); + av_bprint_clear(&s->buffer); for (i=0; inum_rects; i++) { @@ -268,7 +274,7 @@ static int srt_encode_frame(AVCodecContext *avctx, es = ec/ 1000; ec -= 1000*es; srt_print(s,"%d\r\n%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\r\n", ++s->count, sh, sm, ss, sc, eh, em, es, ec); - s->dialog_start = s->ptr - 2; + s->timestamp_end = s->buffer.len - 2; } s->alignment_applied = 0; srt_style_apply(s, dialog->style); @@ -276,23 +282,25 @@ static int srt_encode_frame(AVCodecContext *avctx, } } - if (s->ptr == s->buffer) + if (!av_bprint_is_complete(&s->buffer)) + return AVERROR(ENOMEM); + if (!s->buffer.len) return 0; - len = av_strlcpy(buf, s->buffer, bufsize); - - if (len > bufsize-1) { + if (s->buffer.len > bufsize) { av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); return -1; } + memcpy(buf, s->buffer.str, s->buffer.len); - return len; + return s->buffer.len; } static int srt_encode_close(AVCodecContext *avctx) { SRTContext *s = avctx->priv_data; ff_ass_split_free(s->ass_ctx); + av_bprint_finalize(&s->buffer, NULL); return 0; }