X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fansi.c;h=0bdbdbe071b05e1a4f931da441dc71b7657bd9ea;hb=5c1585c4c3b5281835d784c5daef0069915ccd57;hp=edd373db45a2028eea119ac76836f41ea15a38c3;hpb=df9b9567518f2840d79a4a96b447ebe1aa326408;p=ffmpeg diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c index edd373db45a..0bdbdbe071b 100644 --- a/libavcodec/ansi.c +++ b/libavcodec/ansi.c @@ -25,6 +25,7 @@ */ #include "libavutil/common.h" +#include "libavutil/frame.h" #include "libavutil/lfg.h" #include "avcodec.h" #include "cga_data.h" @@ -48,8 +49,8 @@ static const uint8_t ansi_to_cga[16] = { 0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15 }; -typedef struct { - AVFrame frame; +typedef struct AnsiContext { + AVFrame *frame; int x; /**< x cursor position (pixels) */ int y; /**< y cursor position (pixels) */ int sx; /**< saved x cursor position (pixels) */ @@ -77,15 +78,21 @@ static av_cold int decode_init(AVCodecContext *avctx) AnsiContext *s = avctx->priv_data; avctx->pix_fmt = AV_PIX_FMT_PAL8; + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + /* defaults */ s->font = ff_vga16_font; s->font_height = 16; s->fg = DEFAULT_FG_COLOR; s->bg = DEFAULT_BG_COLOR; - if (!avctx->width || !avctx->height) - avcodec_set_dimensions(avctx, 80<<3, 25<<4); - + if (!avctx->width || !avctx->height) { + int ret = ff_set_dimensions(avctx, 80 << 3, 25 << 4); + if (ret < 0) + return ret; + } return 0; } @@ -101,11 +108,11 @@ static void hscroll(AVCodecContext *avctx) i = 0; for (; i < avctx->height - s->font_height; i++) - memcpy(s->frame.data[0] + i * s->frame.linesize[0], - s->frame.data[0] + (i + s->font_height) * s->frame.linesize[0], + memcpy(s->frame->data[0] + i * s->frame->linesize[0], + s->frame->data[0] + (i + s->font_height) * s->frame->linesize[0], avctx->width); for (; i < avctx->height; i++) - memset(s->frame.data[0] + i * s->frame.linesize[0], + memset(s->frame->data[0] + i * s->frame->linesize[0], DEFAULT_BG_COLOR, avctx->width); } @@ -114,7 +121,7 @@ static void erase_line(AVCodecContext * avctx, int xoffset, int xlength) AnsiContext *s = avctx->priv_data; int i; for (i = 0; i < s->font_height; i++) - memset(s->frame.data[0] + (s->y + i)*s->frame.linesize[0] + xoffset, + memset(s->frame->data[0] + (s->y + i)*s->frame->linesize[0] + xoffset, DEFAULT_BG_COLOR, xlength); } @@ -123,7 +130,7 @@ static void erase_screen(AVCodecContext *avctx) AnsiContext *s = avctx->priv_data; int i; for (i = 0; i < avctx->height; i++) - memset(s->frame.data[0] + i * s->frame.linesize[0], DEFAULT_BG_COLOR, avctx->width); + memset(s->frame->data[0] + i * s->frame->linesize[0], DEFAULT_BG_COLOR, avctx->width); s->x = s->y = 0; } @@ -144,8 +151,8 @@ static void draw_char(AVCodecContext *avctx, int c) FFSWAP(int, fg, bg); if ((s->attributes & ATTR_CONCEALED)) fg = bg; - ff_draw_pc_font(s->frame.data[0] + s->y * s->frame.linesize[0] + s->x, - s->frame.linesize[0], s->font, s->font_height, c, fg, bg); + ff_draw_pc_font(s->frame->data[0] + s->y * s->frame->linesize[0] + s->x, + s->frame->linesize[0], s->font, s->font_height, c, fg, bg); s->x += FONT_WIDTH; if (s->x >= avctx->width) { s->x = 0; @@ -160,7 +167,10 @@ static void draw_char(AVCodecContext *avctx, int c) static int execute_code(AVCodecContext * avctx, int c) { AnsiContext *s = avctx->priv_data; - int ret, i, width, height; + int ret, i; + int width = 0; + int height = 0; + switch(c) { case 'A': //Cursor Up s->y = FFMAX(s->y - (s->nb_args > 0 ? s->args[0]*s->font_height : s->font_height), 0); @@ -179,7 +189,7 @@ static int execute_code(AVCodecContext * avctx, int c) s->y = s->nb_args > 0 ? av_clip((s->args[0] - 1)*s->font_height, 0, avctx->height - s->font_height) : 0; s->x = s->nb_args > 1 ? av_clip((s->args[1] - 1)*FONT_WIDTH, 0, avctx->width - FONT_WIDTH) : 0; break; - case 'h': //set creen mode + case 'h': //set screen mode case 'l': //reset screen mode if (s->nb_args < 2) s->args[0] = DEFAULT_SCREEN_MODE; @@ -217,20 +227,22 @@ static int execute_code(AVCodecContext * avctx, int c) height = 60<<4; break; default: - av_log_ask_for_sample(avctx, "unsupported screen mode\n"); + avpriv_request_sample(avctx, "Unsupported screen mode"); } - if (width != avctx->width || height != avctx->height) { - if (s->frame.data[0]) - avctx->release_buffer(avctx, &s->frame); - avcodec_set_dimensions(avctx, width, height); - ret = ff_get_buffer(avctx, &s->frame); + if (width != 0 && height != 0 && + (width != avctx->width || height != avctx->height)) { + av_frame_unref(s->frame); + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + ret = ff_get_buffer(avctx, s->frame, AV_GET_BUFFER_FLAG_REF); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } - s->frame.pict_type = AV_PICTURE_TYPE_I; - s->frame.palette_has_changed = 1; - memcpy(s->frame.data[1], ff_cga_palette, 16 * 4); + s->frame->pict_type = AV_PICTURE_TYPE_I; + s->frame->palette_has_changed = 1; + memcpy(s->frame->data[1], ff_cga_palette, 16 * 4); erase_screen(avctx); } else if (c == 'l') { erase_screen(avctx); @@ -241,13 +253,13 @@ static int execute_code(AVCodecContext * avctx, int c) case 0: erase_line(avctx, s->x, avctx->width - s->x); if (s->y < avctx->height - s->font_height) - memset(s->frame.data[0] + (s->y + s->font_height)*s->frame.linesize[0], - DEFAULT_BG_COLOR, (avctx->height - s->y - s->font_height)*s->frame.linesize[0]); + memset(s->frame->data[0] + (s->y + s->font_height)*s->frame->linesize[0], + DEFAULT_BG_COLOR, (avctx->height - s->y - s->font_height)*s->frame->linesize[0]); break; case 1: erase_line(avctx, 0, s->x); if (s->y > 0) - memset(s->frame.data[0], DEFAULT_BG_COLOR, s->y * s->frame.linesize[0]); + memset(s->frame->data[0], DEFAULT_BG_COLOR, s->y * s->frame->linesize[0]); break; case 2: erase_screen(avctx); @@ -287,7 +299,7 @@ static int execute_code(AVCodecContext * avctx, int c) } else if (m == 49) { s->fg = ansi_to_cga[DEFAULT_BG_COLOR]; } else { - av_log_ask_for_sample(avctx, "unsupported rendition parameter\n"); + avpriv_request_sample(avctx, "Unsupported rendition parameter"); } } break; @@ -304,7 +316,7 @@ static int execute_code(AVCodecContext * avctx, int c) s->y = av_clip(s->sy, 0, avctx->height - s->font_height); break; default: - av_log_ask_for_sample(avctx, "unsupported escape code\n"); + avpriv_request_sample(avctx, "Unknown escape code"); break; } return 0; @@ -320,14 +332,19 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *buf_end = buf+buf_size; int ret, i, count; - ret = avctx->reget_buffer(avctx, &s->frame); + ret = ff_reget_buffer(avctx, s->frame); if (ret < 0){ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } - s->frame.pict_type = AV_PICTURE_TYPE_I; - s->frame.palette_has_changed = 1; - memcpy(s->frame.data[1], ff_cga_palette, 16 * 4); + if (!avctx->frame_number) { + memset(s->frame->data[0], 0, avctx->height * FFABS(s->frame->linesize[0])); + memset(s->frame->data[1], 0, AVPALETTE_SIZE); + } + + s->frame->pict_type = AV_PICTURE_TYPE_I; + s->frame->palette_has_changed = 1; + memcpy(s->frame->data[1], ff_cga_palette, 16 * 4); while(buf < buf_end) { switch(s->state) { @@ -370,7 +387,6 @@ static int decode_frame(AVCodecContext *avctx, } else { s->state = STATE_NORMAL; draw_char(avctx, 0x1B); - return -1; continue; } break; @@ -397,8 +413,8 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_WARNING, "args overflow (%i)\n", s->nb_args); if (s->nb_args < MAX_NB_ARGS && s->args[s->nb_args]) s->nb_args++; - if (execute_code(avctx, buf[0]) < 0) - return -1; + if ((ret = execute_code(avctx, buf[0])) < 0) + return ret; s->state = STATE_NORMAL; } break; @@ -412,26 +428,28 @@ static int decode_frame(AVCodecContext *avctx, } *got_frame = 1; - *(AVFrame*)data = s->frame; + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; return buf_size; } static av_cold int decode_close(AVCodecContext *avctx) { AnsiContext *s = avctx->priv_data; - if (s->frame.data[0]) - avctx->release_buffer(avctx, &s->frame); + + av_frame_free(&s->frame); return 0; } AVCodec ff_ansi_decoder = { .name = "ansi", + .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_ANSI, .priv_data_size = sizeof(AnsiContext), .init = decode_init, .close = decode_close, .decode = decode_frame, - .capabilities = CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, };