*/
#include "libavutil/common.h"
+#include "libavutil/frame.h"
#include "libavutil/lfg.h"
#include "avcodec.h"
#include "cga_data.h"
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) */
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;
}
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);
}
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);
}
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;
}
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;
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);
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;
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);
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);
} 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;
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;
}
static int decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
+ void *data, int *got_frame,
AVPacket *avpkt)
{
AnsiContext *s = avctx->priv_data;
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) {
} else {
s->state = STATE_NORMAL;
draw_char(avctx, 0x1B);
- return -1;
continue;
}
break;
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;
buf++;
}
- *data_size = sizeof(AVFrame);
- *(AVFrame*)data = s->frame;
+ *got_frame = 1;
+ 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,
};