/src/ffmpeg/libavcodec/aasc.c
Line | Count | Source |
1 | | /* |
2 | | * Autodesk RLE Decoder |
3 | | * Copyright (C) 2005 The FFmpeg project |
4 | | * |
5 | | * This file is part of FFmpeg. |
6 | | * |
7 | | * FFmpeg is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * FFmpeg is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with FFmpeg; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | /** |
23 | | * @file |
24 | | * Autodesk RLE Video Decoder by Konstantin Shishkov |
25 | | */ |
26 | | |
27 | | #include <string.h> |
28 | | |
29 | | #include "avcodec.h" |
30 | | #include "codec_internal.h" |
31 | | #include "decode.h" |
32 | | #include "msrledec.h" |
33 | | |
34 | | typedef struct AascContext { |
35 | | AVCodecContext *avctx; |
36 | | GetByteContext gb; |
37 | | AVFrame *frame; |
38 | | |
39 | | uint32_t palette[AVPALETTE_COUNT]; |
40 | | int palette_size; |
41 | | } AascContext; |
42 | | |
43 | | static av_cold int aasc_decode_init(AVCodecContext *avctx) |
44 | 800 | { |
45 | 800 | AascContext *s = avctx->priv_data; |
46 | 800 | uint8_t *ptr; |
47 | 800 | int i; |
48 | | |
49 | 800 | s->avctx = avctx; |
50 | 800 | switch (avctx->bits_per_coded_sample) { |
51 | 321 | case 8: |
52 | 321 | avctx->pix_fmt = AV_PIX_FMT_PAL8; |
53 | | |
54 | 321 | ptr = avctx->extradata; |
55 | 321 | s->palette_size = FFMIN(avctx->extradata_size, AVPALETTE_SIZE); |
56 | 5.72k | for (i = 0; i < s->palette_size / 4; i++) { |
57 | 5.40k | s->palette[i] = 0xFFU << 24 | AV_RL32(ptr); |
58 | 5.40k | ptr += 4; |
59 | 5.40k | } |
60 | 321 | break; |
61 | 182 | case 16: |
62 | 182 | avctx->pix_fmt = AV_PIX_FMT_RGB555LE; |
63 | 182 | break; |
64 | 180 | case 24: |
65 | 180 | avctx->pix_fmt = AV_PIX_FMT_BGR24; |
66 | 180 | break; |
67 | 117 | default: |
68 | 117 | av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", avctx->bits_per_coded_sample); |
69 | 117 | return -1; |
70 | 800 | } |
71 | | |
72 | 683 | s->frame = av_frame_alloc(); |
73 | 683 | if (!s->frame) |
74 | 0 | return AVERROR(ENOMEM); |
75 | | |
76 | 683 | return 0; |
77 | 683 | } |
78 | | |
79 | | static int aasc_decode_frame(AVCodecContext *avctx, AVFrame *rframe, |
80 | | int *got_frame, AVPacket *avpkt) |
81 | 178k | { |
82 | 178k | const uint8_t *buf = avpkt->data; |
83 | 178k | int buf_size = avpkt->size; |
84 | 178k | AascContext *s = avctx->priv_data; |
85 | 178k | int compr, i, stride, psize, ret; |
86 | | |
87 | 178k | if (buf_size < 4) { |
88 | 40.4k | av_log(avctx, AV_LOG_ERROR, "frame too short\n"); |
89 | 40.4k | return AVERROR_INVALIDDATA; |
90 | 40.4k | } |
91 | | |
92 | 137k | if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) |
93 | 5.03k | return ret; |
94 | | |
95 | 132k | compr = AV_RL32(buf); |
96 | 132k | buf += 4; |
97 | 132k | buf_size -= 4; |
98 | 132k | psize = avctx->bits_per_coded_sample / 8; |
99 | 132k | switch (avctx->codec_tag) { |
100 | 125k | case MKTAG('A', 'A', 'S', '4'): |
101 | 125k | bytestream2_init(&s->gb, buf - 4, buf_size + 4); |
102 | 125k | ff_msrle_decode(avctx, s->frame, 8, &s->gb); |
103 | 125k | break; |
104 | 2.18k | case MKTAG('A', 'A', 'S', 'C'): |
105 | 2.18k | switch (compr) { |
106 | 524 | case 0: |
107 | 524 | stride = (avctx->width * psize + psize) & ~psize; |
108 | 524 | if (buf_size < stride * avctx->height) |
109 | 285 | return AVERROR_INVALIDDATA; |
110 | 54.5k | for (i = avctx->height - 1; i >= 0; i--) { |
111 | 54.3k | memcpy(s->frame->data[0] + i * s->frame->linesize[0], buf, avctx->width * psize); |
112 | 54.3k | buf += stride; |
113 | 54.3k | buf_size -= stride; |
114 | 54.3k | } |
115 | 239 | break; |
116 | 710 | case 1: |
117 | 710 | bytestream2_init(&s->gb, buf, buf_size); |
118 | 710 | ff_msrle_decode(avctx, s->frame, 8, &s->gb); |
119 | 710 | break; |
120 | 946 | default: |
121 | 946 | av_log(avctx, AV_LOG_ERROR, "Unknown compression type %d\n", compr); |
122 | 946 | return AVERROR_INVALIDDATA; |
123 | 2.18k | } |
124 | 949 | break; |
125 | 5.61k | default: |
126 | 5.61k | av_log(avctx, AV_LOG_ERROR, "Unknown FourCC: %X\n", avctx->codec_tag); |
127 | 5.61k | return -1; |
128 | 132k | } |
129 | | |
130 | 126k | if (avctx->pix_fmt == AV_PIX_FMT_PAL8) |
131 | 119k | memcpy(s->frame->data[1], s->palette, s->palette_size); |
132 | | |
133 | 126k | *got_frame = 1; |
134 | 126k | if ((ret = av_frame_ref(rframe, s->frame)) < 0) |
135 | 0 | return ret; |
136 | | |
137 | | /* report that the buffer was completely consumed */ |
138 | 126k | return avpkt->size; |
139 | 126k | } |
140 | | |
141 | | static av_cold int aasc_decode_end(AVCodecContext *avctx) |
142 | 683 | { |
143 | 683 | AascContext *s = avctx->priv_data; |
144 | | |
145 | 683 | av_frame_free(&s->frame); |
146 | | |
147 | 683 | return 0; |
148 | 683 | } |
149 | | |
150 | | const FFCodec ff_aasc_decoder = { |
151 | | .p.name = "aasc", |
152 | | CODEC_LONG_NAME("Autodesk RLE"), |
153 | | .p.type = AVMEDIA_TYPE_VIDEO, |
154 | | .p.id = AV_CODEC_ID_AASC, |
155 | | .priv_data_size = sizeof(AascContext), |
156 | | .init = aasc_decode_init, |
157 | | .close = aasc_decode_end, |
158 | | FF_CODEC_DECODE_CB(aasc_decode_frame), |
159 | | .p.capabilities = AV_CODEC_CAP_DR1, |
160 | | }; |