Imported Upstream version 6.1
[platform/upstream/ffmpeg.git] / libavcodec / msrleenc.c
1 /*
2  * Copyright (c) 2023 Tomas Härdin
3  *
4  * This file is part of FFmpeg.
5  *
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.
10  *
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.
15  *
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
19  */
20
21 /**
22  * @file
23  * MSRLE encoder
24  * @see https://wiki.multimedia.cx/index.php?title=Microsoft_RLE
25  */
26
27 // TODO: pal4 mode?
28
29 #include "bytestream.h"
30 #include "codec_internal.h"
31 #include "encode.h"
32
33 typedef struct MSRLEContext {
34     int curframe;
35     AVFrame *last_frame;
36 } MSRLEContext;
37
38 static av_cold int msrle_encode_init(AVCodecContext *avctx)
39 {
40     MSRLEContext *s = avctx->priv_data;
41
42     avctx->bits_per_coded_sample = 8;
43     s->last_frame = av_frame_alloc();
44     if (!s->last_frame)
45         return AVERROR(ENOMEM);
46
47     return 0;
48 }
49
50 static void write_run(AVCodecContext *avctx, uint8_t **data, int len, int value)
51 {
52     // we're allowed to write odd runs
53     while (len >= 255) {
54         bytestream_put_byte(data, 255);
55         bytestream_put_byte(data, value);
56         len -= 255;
57     }
58     if (len >= 1) {
59         // this is wasteful when len == 1 and sometimes when len == 2
60         // but sometimes we have no choice. also write_absolute()
61         // relies on this
62         bytestream_put_byte(data, len);
63         bytestream_put_byte(data, value);
64     }
65 }
66
67 static void write_absolute(AVCodecContext *avctx, uint8_t **data,
68                            const uint8_t *line, int len)
69 {
70     // writing 255 would be wasteful here due to the padding requirement
71     while (len >= 254) {
72         bytestream_put_byte(data, 0);
73         bytestream_put_byte(data, 254);
74         bytestream_put_buffer(data, line, 254);
75         line += 254;
76         len -= 254;
77     }
78     if (len == 1) {
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]);
85     } else if (len > 0) {
86         bytestream_put_byte(data, 0);
87         bytestream_put_byte(data, len);
88         bytestream_put_buffer(data, line, len);
89         if (len & 1)
90             bytestream_put_byte(data, 0);
91     }
92 }
93
94 static void write_delta(AVCodecContext *avctx, uint8_t **data, int delta)
95 {
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);
105         delta -= 255;
106     }
107     if (delta > 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);
112     }
113 }
114
115 static void write_yskip(AVCodecContext *avctx, uint8_t **data, int yskip)
116 {
117     if (yskip < 4)
118         return;
119     // we have yskip*2 nul bytess
120     *data -= 2*yskip;
121     // the end-of-line counts as one skip
122     yskip--;
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);
128         yskip -= 255;
129     }
130     if (yskip > 0) {
131         bytestream_put_byte(data, 0);
132         bytestream_put_byte(data, 2);
133         bytestream_put_byte(data, 0);
134         bytestream_put_byte(data, yskip);
135     }
136     bytestream_put_be16(data, 0x0000);
137 }
138
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)
142 {
143     int run = 0, last = -1, absstart = 0;
144     if (length == 0)
145         return;
146     for (int x = 0; x < length; x++) {
147         if (last == line[x]) {
148             run++;
149             if (run == 3)
150                 write_absolute(avctx, data, &line[absstart], x - absstart - 2);
151         } else {
152             if (run >= 3) {
153                 write_run(avctx, data, run, last);
154                 absstart = x;
155             }
156             run = 1;
157         }
158         last = line[x];
159     }
160     if (run >= 3)
161         write_run(avctx, data, run, last);
162     else
163         write_absolute(avctx, data, &line[absstart], length - absstart);
164 }
165
166 static int encode(AVCodecContext *avctx, AVPacket *pkt,
167                   const AVFrame *pict, int keyframe, int *got_keyframe)
168 {
169     MSRLEContext *s = avctx->priv_data;
170     uint8_t *data = pkt->data;
171
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:
174
175             00 00           end of line
176             00 01           end of bitmap
177             00 02 dx dy     delta. move pointer to x+dx, y+dy
178             00 ll dd dd ..  absolute (verbatim) mode. ll >= 3
179             rr dd           run. rr >= 1
180
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.
184     */
185     *got_keyframe = 1;  // set to zero whenever we use a feature that makes this a not-keyframe
186
187     if (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
192         }
193     } else {
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]) {
203                     delta++;
204                     if (delta == 5) {
205                         int len = x - linestart - 4;
206                         if (len > 0) {
207                             write_yskip(avctx, &data, yskip);
208                             yskip = 0;
209                             encode_line(avctx, &data, &line[linestart], len);
210                             encoded = 1;
211                         }
212                         linestart = -1;
213                     }
214                 } else {
215                     if (delta >= 5) {
216                         write_yskip(avctx, &data, yskip);
217                         yskip = 0;
218                         write_delta(avctx, &data, delta);
219                         *got_keyframe = 0;
220                         encoded = 1;
221                     }
222                     delta = 0;
223                     if (linestart == -1)
224                         linestart = x;
225                 }
226             }
227             if (delta < 5) {
228                 write_yskip(avctx, &data, yskip);
229                 yskip = 0;
230                 encode_line(avctx, &data, &line[linestart], avctx->width - linestart);
231                 encoded  = 1;
232             } else
233                 *got_keyframe = 0;
234             bytestream_put_be16(&data, 0x0000); // end of line
235             if (!encoded)
236                 yskip++;
237             else
238                 yskip = 0;
239         }
240         write_yskip(avctx, &data, yskip);
241     }
242     bytestream_put_be16(&data, 0x0001); // end of bitmap
243     pkt->size = data - pkt->data;
244     return 0;
245 }
246
247 static int msrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
248                               const AVFrame *pict, int *got_packet)
249 {
250     MSRLEContext *s = avctx->priv_data;
251     int ret, got_keyframe;
252
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)))
256         return ret;
257
258     if (pict->data[1]) {
259         uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
260         if (!side_data)
261             return AVERROR(ENOMEM);
262         memcpy(side_data, pict->data[1], AVPALETTE_SIZE);
263     }
264
265     if ((ret = encode(avctx, pkt, pict, s->curframe == 0, &got_keyframe)))
266         return ret;
267
268     if (got_keyframe) {
269         pkt->flags |= AV_PKT_FLAG_KEY;
270         s->curframe = 0;
271     }
272     if (++s->curframe >= avctx->gop_size)
273         s->curframe = 0;
274     *got_packet = 1;
275
276     return av_frame_replace(s->last_frame, pict);
277 }
278
279 static int msrle_encode_close(AVCodecContext *avctx)
280 {
281     MSRLEContext *s = avctx->priv_data;
282     av_frame_free(&s->last_frame);
283     return 0;
284 }
285
286 const FFCodec ff_msrle_encoder = {
287     .p.name         = "msrle",
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
298     },
299     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
300 };