X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fsunrast.c;h=6a928bb2cf50f167f7c9a0c5b2885c40480e4a35;hb=8f144d9e3d5cb2ca92e5bdf7cc9f72effa1bd2ce;hp=d63fd171b8a3b5da4c2c139f66200102755c3363;hpb=ec6402b7c595c3ceed6d1b8c1b75c6aa8336e052;p=ffmpeg diff --git a/libavcodec/sunrast.c b/libavcodec/sunrast.c index d63fd171b8a..6a928bb2cf5 100644 --- a/libavcodec/sunrast.c +++ b/libavcodec/sunrast.c @@ -19,114 +19,101 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "avcodec.h" - -#define RT_OLD 0 -#define RT_STANDARD 1 -#define RT_BYTE_ENCODED 2 -#define RT_FORMAT_RGB 3 -#define RT_FORMAT_TIFF 4 -#define RT_FORMAT_IFF 5 - -typedef struct SUNRASTContext { - AVFrame picture; -} SUNRASTContext; - -static av_cold int sunrast_init(AVCodecContext *avctx) { - SUNRASTContext *s = avctx->priv_data; - - avcodec_get_frame_defaults(&s->picture); - avctx->coded_frame= &s->picture; - - return 0; -} +#include "internal.h" +#include "sunrast.h" static int sunrast_decode_frame(AVCodecContext *avctx, void *data, - int *data_size, AVPacket *avpkt) { - const uint8_t *buf = avpkt->data; - SUNRASTContext * const s = avctx->priv_data; - AVFrame *picture = data; - AVFrame * const p = &s->picture; + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = avpkt->data + avpkt->size; + AVFrame * const p = data; unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen; uint8_t *ptr; const uint8_t *bufstart = buf; + int ret; - if (AV_RB32(buf) != 0x59a66a95) { + if (avpkt->size < 32) + return AVERROR_INVALIDDATA; + + if (AV_RB32(buf) != RAS_MAGIC) { av_log(avctx, AV_LOG_ERROR, "this is not sunras encoded data\n"); - return -1; + return AVERROR_INVALIDDATA; } - w = AV_RB32(buf+4); - h = AV_RB32(buf+8); - depth = AV_RB32(buf+12); - type = AV_RB32(buf+20); - maptype = AV_RB32(buf+24); - maplength = AV_RB32(buf+28); - - if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) { - av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n"); - return -1; + w = AV_RB32(buf + 4); + h = AV_RB32(buf + 8); + depth = AV_RB32(buf + 12); + type = AV_RB32(buf + 20); + maptype = AV_RB32(buf + 24); + maplength = AV_RB32(buf + 28); + buf += 32; + + if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF || type == RT_EXPERIMENTAL) { + avpriv_request_sample(avctx, "TIFF/IFF/EXPERIMENTAL (compression) type"); + return AVERROR_PATCHWELCOME; } if (type > RT_FORMAT_IFF) { av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n"); - return -1; + return AVERROR_INVALIDDATA; } - if (maptype & ~1) { + if (maptype == RMT_RAW) { + avpriv_request_sample(avctx, "Unknown colormap type"); + return AVERROR_PATCHWELCOME; + } + if (maptype > RMT_RAW) { av_log(avctx, AV_LOG_ERROR, "invalid colormap type\n"); - return -1; + return AVERROR_INVALIDDATA; } - buf += 32; switch (depth) { case 1: - avctx->pix_fmt = PIX_FMT_MONOWHITE; + avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; break; case 8: - avctx->pix_fmt = PIX_FMT_PAL8; + avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8; break; case 24: - avctx->pix_fmt = (type == RT_FORMAT_RGB) ? PIX_FMT_RGB24 : PIX_FMT_BGR24; + avctx->pix_fmt = (type == RT_FORMAT_RGB) ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_BGR24; break; default: av_log(avctx, AV_LOG_ERROR, "invalid depth\n"); - return -1; + return AVERROR_INVALIDDATA; } - if (p->data[0]) - avctx->release_buffer(avctx, p); + ret = ff_set_dimensions(avctx, w, h); + if (ret < 0) + return ret; - if (av_image_check_size(w, h, 0, avctx)) - return -1; - if (w != avctx->width || h != avctx->height) - avcodec_set_dimensions(avctx, w, h); - if (avctx->get_buffer(avctx, p) < 0) { + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - return -1; + return ret; } p->pict_type = AV_PICTURE_TYPE_I; + if (buf_end - buf < maplength) + return AVERROR_INVALIDDATA; + if (depth != 8 && maplength) { av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n"); - } else if (depth == 8) { + } else if (maplength) { unsigned int len = maplength / 3; - if (!maplength) { - av_log(avctx, AV_LOG_ERROR, "colormap expected\n"); - return -1; - } if (maplength % 3 || maplength > 768) { av_log(avctx, AV_LOG_WARNING, "invalid colormap length\n"); - return -1; + return AVERROR_INVALIDDATA; } ptr = p->data[1]; - for (x=0; x> 3; - alen = len + (len&1); + alen = len + (len & 1); if (type == RT_BYTE_ENCODED) { int value, run; - uint8_t *end = ptr + h*stride; + uint8_t *end = ptr + h * stride; x = 0; - while (ptr != end) { + while (ptr != end && buf < buf_end) { run = 1; - if ((value = *buf++) == 0x80) { + if (buf_end - buf < 1) + return AVERROR_INVALIDDATA; + + if ((value = *buf++) == RLE_TRIGGER) { run = *buf++ + 1; if (run != 1) value = *buf++; @@ -162,36 +152,25 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, } } } else { - for (y=0; ypicture; - *data_size = sizeof(AVFrame); + *got_frame = 1; return buf - bufstart; } -static av_cold int sunrast_end(AVCodecContext *avctx) { - SUNRASTContext *s = avctx->priv_data; - - if(s->picture.data[0]) - avctx->release_buffer(avctx, &s->picture); - - return 0; -} - AVCodec ff_sunrast_decoder = { .name = "sunrast", + .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), .type = AVMEDIA_TYPE_VIDEO, - .id = CODEC_ID_SUNRAST, - .priv_data_size = sizeof(SUNRASTContext), - .init = sunrast_init, - .close = sunrast_end, + .id = AV_CODEC_ID_SUNRAST, .decode = sunrast_decode_frame, - .capabilities = CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), + .capabilities = AV_CODEC_CAP_DR1, };