2 * Microsoft RLE video decoder
3 * Copyright (c) 2003 The FFmpeg Project
5 * This file is part of FFmpeg.
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.
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.
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
24 * MS RLE video decoder by Mike Melanson (melanson@pcisys.net)
25 * For more information about the MS RLE format, visit:
26 * http://www.pcisys.net/~melanson/codecs/
28 * The MS RLE decoder outputs PAL8 colorspace data.
38 #include "libavutil/imgutils.h"
40 typedef struct MsrleContext
{
41 AVCodecContext
*avctx
;
45 const unsigned char *buf
;
51 static av_cold
int msrle_decode_init(AVCodecContext
*avctx
)
53 MsrleContext
*s
= avctx
->priv_data
;
58 switch (avctx
->bits_per_coded_sample
) {
60 avctx
->pix_fmt
= AV_PIX_FMT_MONOWHITE
;
64 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
67 avctx
->pix_fmt
= AV_PIX_FMT_BGR24
;
70 av_log(avctx
, AV_LOG_ERROR
, "unsupported bits per sample\n");
71 return AVERROR_INVALIDDATA
;
74 s
->frame
= av_frame_alloc();
76 return AVERROR(ENOMEM
);
78 if (avctx
->extradata_size
>= 4)
79 for (i
= 0; i
< FFMIN(avctx
->extradata_size
, AVPALETTE_SIZE
)/4; i
++)
80 s
->pal
[i
] = 0xFFU
<<24 | AV_RL32(avctx
->extradata
+4*i
);
85 static int msrle_decode_frame(AVCodecContext
*avctx
,
86 void *data
, int *got_frame
,
89 const uint8_t *buf
= avpkt
->data
;
90 int buf_size
= avpkt
->size
;
91 MsrleContext
*s
= avctx
->priv_data
;
92 int istride
= FFALIGN(avctx
->width
*avctx
->bits_per_coded_sample
, 32) / 8;
98 if ((ret
= ff_reget_buffer(avctx
, s
->frame
)) < 0)
101 if (avctx
->bits_per_coded_sample
> 1 && avctx
->bits_per_coded_sample
<= 8) {
102 const uint8_t *pal
= av_packet_get_side_data(avpkt
, AV_PKT_DATA_PALETTE
, NULL
);
105 s
->frame
->palette_has_changed
= 1;
106 memcpy(s
->pal
, pal
, AVPALETTE_SIZE
);
108 /* make the palette available */
109 memcpy(s
->frame
->data
[1], s
->pal
, AVPALETTE_SIZE
);
112 /* FIXME how to correctly detect RLE ??? */
113 if (avctx
->height
* istride
== avpkt
->size
) { /* assume uncompressed */
114 int linesize
= av_image_get_linesize(avctx
->pix_fmt
, avctx
->width
, 0);
115 uint8_t *ptr
= s
->frame
->data
[0];
116 uint8_t *buf
= avpkt
->data
+ (avctx
->height
-1)*istride
;
122 for (i
= 0; i
< avctx
->height
; i
++) {
123 if (avctx
->bits_per_coded_sample
== 4) {
124 for (j
= 0; j
< avctx
->width
- 1; j
+= 2) {
125 ptr
[j
+0] = buf
[j
>>1] >> 4;
126 ptr
[j
+1] = buf
[j
>>1] & 0xF;
128 if (avctx
->width
& 1)
129 ptr
[j
+0] = buf
[j
>>1] >> 4;
131 memcpy(ptr
, buf
, linesize
);
134 ptr
+= s
->frame
->linesize
[0];
137 bytestream2_init(&s
->gb
, buf
, buf_size
);
138 ff_msrle_decode(avctx
, (AVPicture
*)s
->frame
, avctx
->bits_per_coded_sample
, &s
->gb
);
141 if ((ret
= av_frame_ref(data
, s
->frame
)) < 0)
146 /* report that the buffer was completely consumed */
150 static av_cold
int msrle_decode_end(AVCodecContext
*avctx
)
152 MsrleContext
*s
= avctx
->priv_data
;
154 /* release the last frame */
155 av_frame_free(&s
->frame
);
160 AVCodec ff_msrle_decoder
= {
162 .long_name
= NULL_IF_CONFIG_SMALL("Microsoft RLE"),
163 .type
= AVMEDIA_TYPE_VIDEO
,
164 .id
= AV_CODEC_ID_MSRLE
,
165 .priv_data_size
= sizeof(MsrleContext
),
166 .init
= msrle_decode_init
,
167 .close
= msrle_decode_end
,
168 .decode
= msrle_decode_frame
,
169 .capabilities
= CODEC_CAP_DR1
,