2 * Copyright (c) 2023 Tomas Härdin
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * @see https://wiki.multimedia.cx/index.php?title=Microsoft_RLE
29 #include "bytestream.h"
30 #include "codec_internal.h"
33 typedef struct MSRLEContext {
38 static av_cold int msrle_encode_init(AVCodecContext *avctx)
40 MSRLEContext *s = avctx->priv_data;
42 avctx->bits_per_coded_sample = 8;
43 s->last_frame = av_frame_alloc();
45 return AVERROR(ENOMEM);
50 static void write_run(AVCodecContext *avctx, uint8_t **data, int len, int value)
52 // we're allowed to write odd runs
54 bytestream_put_byte(data, 255);
55 bytestream_put_byte(data, value);
59 // this is wasteful when len == 1 and sometimes when len == 2
60 // but sometimes we have no choice. also write_absolute()
62 bytestream_put_byte(data, len);
63 bytestream_put_byte(data, value);
67 static void write_absolute(AVCodecContext *avctx, uint8_t **data,
68 const uint8_t *line, int len)
70 // writing 255 would be wasteful here due to the padding requirement
72 bytestream_put_byte(data, 0);
73 bytestream_put_byte(data, 254);
74 bytestream_put_buffer(data, line, 254);
79 // it's less wasteful to write single pixels as runs
80 // not to mention that absolute mode requires >= 3 pixels
81 write_run(avctx, data, 1, line[0]);
82 } else if (len == 2) {
83 write_run(avctx, data, 1, line[0]);
84 write_run(avctx, data, 1, line[1]);
86 bytestream_put_byte(data, 0);
87 bytestream_put_byte(data, len);
88 bytestream_put_buffer(data, line, len);
90 bytestream_put_byte(data, 0);
94 static void write_delta(AVCodecContext *avctx, uint8_t **data, int delta)
96 // we let the yskip logic handle the case where we want to delta
97 // to following lines. it's not perfect but it's easier than finding
98 // the optimal combination of end-of-lines and deltas to reach any
99 // following position including places where dx < 0
100 while (delta >= 255) {
101 bytestream_put_byte(data, 0);
102 bytestream_put_byte(data, 2);
103 bytestream_put_byte(data, 255);
104 bytestream_put_byte(data, 0);
108 bytestream_put_byte(data, 0);
109 bytestream_put_byte(data, 2);
110 bytestream_put_byte(data, delta);
111 bytestream_put_byte(data, 0);
115 static void write_yskip(AVCodecContext *avctx, uint8_t **data, int yskip)
119 // we have yskip*2 nul bytess
121 // the end-of-line counts as one skip
123 while (yskip >= 255) {
124 bytestream_put_byte(data, 0);
125 bytestream_put_byte(data, 2);
126 bytestream_put_byte(data, 0);
127 bytestream_put_byte(data, 255);
131 bytestream_put_byte(data, 0);
132 bytestream_put_byte(data, 2);
133 bytestream_put_byte(data, 0);
134 bytestream_put_byte(data, yskip);
136 bytestream_put_be16(data, 0x0000);
139 // used both to encode lines in keyframes and to encode lines between deltas
140 static void encode_line(AVCodecContext *avctx, uint8_t **data,
141 const uint8_t *line, int length)
143 int run = 0, last = -1, absstart = 0;
146 for (int x = 0; x < length; x++) {
147 if (last == line[x]) {
150 write_absolute(avctx, data, &line[absstart], x - absstart - 2);
153 write_run(avctx, data, run, last);
161 write_run(avctx, data, run, last);
163 write_absolute(avctx, data, &line[absstart], length - absstart);
166 static int encode(AVCodecContext *avctx, AVPacket *pkt,
167 const AVFrame *pict, int keyframe, int *got_keyframe)
169 MSRLEContext *s = avctx->priv_data;
170 uint8_t *data = pkt->data;
172 /* Compare the current frame to the last frame, or code the entire frame
173 if keyframe != 0. We're continually outputting pairs of bytes:
177 00 02 dx dy delta. move pointer to x+dx, y+dy
178 00 ll dd dd .. absolute (verbatim) mode. ll >= 3
181 For keyframes we only have absolute mode and runs at our disposal, and
182 we are not allowed to end a line early. If this happens when keyframe == 0
183 then *got_keyframe is set to 1 and s->curframe is reset.
185 *got_keyframe = 1; // set to zero whenever we use a feature that makes this a not-keyframe
188 for (int y = avctx->height-1; y >= 0; y--) {
189 uint8_t *line = &pict->data[0][y*pict->linesize[0]];
190 encode_line(avctx, &data, line, avctx->width);
191 bytestream_put_be16(&data, 0x0000); // end of line
194 // compare to previous frame
195 int yskip = 0; // we can encode large skips using deltas
196 for (int y = avctx->height-1; y >= 0; y--) {
197 const uint8_t *line = &pict->data[0][y*pict->linesize[0]];
198 const uint8_t *prev = &s->last_frame->data[0][y*s->last_frame->linesize[0]];
199 // we need at least 5 pixels in a row for a delta to be worthwhile
200 int delta = 0, linestart = 0, encoded = 0;
201 for (int x = 0; x < avctx->width; x++) {
202 if (line[x] == prev[x]) {
205 int len = x - linestart - 4;
207 write_yskip(avctx, &data, yskip);
209 encode_line(avctx, &data, &line[linestart], len);
216 write_yskip(avctx, &data, yskip);
218 write_delta(avctx, &data, delta);
228 write_yskip(avctx, &data, yskip);
230 encode_line(avctx, &data, &line[linestart], avctx->width - linestart);
234 bytestream_put_be16(&data, 0x0000); // end of line
240 write_yskip(avctx, &data, yskip);
242 bytestream_put_be16(&data, 0x0001); // end of bitmap
243 pkt->size = data - pkt->data;
247 static int msrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
248 const AVFrame *pict, int *got_packet)
250 MSRLEContext *s = avctx->priv_data;
251 int ret, got_keyframe;
253 if ((ret = ff_alloc_packet(avctx, pkt, (
254 avctx->width*2 /* worst case = rle every pixel */ + 2 /*end of line */
255 ) * avctx->height + 2 /* end of bitmap */ + AV_INPUT_BUFFER_MIN_SIZE)))
259 uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
261 return AVERROR(ENOMEM);
262 memcpy(side_data, pict->data[1], AVPALETTE_SIZE);
265 if ((ret = encode(avctx, pkt, pict, s->curframe == 0, &got_keyframe)))
269 pkt->flags |= AV_PKT_FLAG_KEY;
272 if (++s->curframe >= avctx->gop_size)
276 return av_frame_replace(s->last_frame, pict);
279 static int msrle_encode_close(AVCodecContext *avctx)
281 MSRLEContext *s = avctx->priv_data;
282 av_frame_free(&s->last_frame);
286 const FFCodec ff_msrle_encoder = {
288 CODEC_LONG_NAME("Microsoft RLE"),
289 .p.type = AVMEDIA_TYPE_VIDEO,
290 .p.id = AV_CODEC_ID_MSRLE,
291 .p.capabilities = AV_CODEC_CAP_DR1,
292 .priv_data_size = sizeof(MSRLEContext),
293 .init = msrle_encode_init,
294 FF_CODEC_ENCODE_CB(msrle_encode_frame),
295 .close = msrle_encode_close,
296 .p.pix_fmts = (const enum AVPixelFormat[]){
297 AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE
299 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,