xref: /third_party/ffmpeg/libavcodec/notchlc.c (revision cabdff1a)
1/*
2 * NotchLC decoder
3 * Copyright (c) 2020 Paul B Mahol
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#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#define BITSTREAM_READER_LE
27#include "libavutil/intreadwrite.h"
28#include "avcodec.h"
29#include "bytestream.h"
30#include "codec_internal.h"
31#include "get_bits.h"
32#include "internal.h"
33#include "lzf.h"
34#include "thread.h"
35
36typedef struct NotchLCContext {
37    unsigned compressed_size;
38    unsigned format;
39
40    uint8_t *uncompressed_buffer;
41    unsigned uncompressed_size;
42
43    uint8_t *lzf_buffer;
44    int64_t lzf_size;
45
46    unsigned texture_size_x;
47    unsigned texture_size_y;
48    unsigned y_data_row_offsets;
49    unsigned uv_offset_data_offset;
50    unsigned y_control_data_offset;
51    unsigned a_control_word_offset;
52    unsigned y_data_offset;
53    unsigned uv_data_offset;
54    unsigned y_data_size;
55    unsigned a_data_offset;
56    unsigned uv_count_offset;
57    unsigned a_count_size;
58    unsigned data_end;
59
60    GetByteContext gb;
61    PutByteContext pb;
62} NotchLCContext;
63
64static av_cold int decode_init(AVCodecContext *avctx)
65{
66    avctx->pix_fmt = AV_PIX_FMT_YUVA444P12;
67    avctx->color_range = AVCOL_RANGE_JPEG;
68    avctx->colorspace = AVCOL_SPC_RGB;
69    avctx->color_primaries = AVCOL_PRI_BT709;
70    avctx->color_trc = AVCOL_TRC_IEC61966_2_1;
71
72    return 0;
73}
74
75#define HISTORY_SIZE (64 * 1024)
76
77static int lz4_decompress(AVCodecContext *avctx,
78                          GetByteContext *gb,
79                          PutByteContext *pb)
80{
81    unsigned reference_pos, match_length, delta, pos = 0;
82    uint8_t history[64 * 1024];
83
84    while (bytestream2_get_bytes_left(gb) > 0) {
85        uint8_t token = bytestream2_get_byte(gb);
86        unsigned num_literals = token >> 4;
87
88        if (num_literals == 15) {
89            unsigned char current;
90            do {
91                current = bytestream2_get_byte(gb);
92                num_literals += current;
93            } while (current == 255);
94        }
95
96        if (pos + num_literals < HISTORY_SIZE) {
97            bytestream2_get_buffer(gb, history + pos, num_literals);
98            pos += num_literals;
99        } else {
100            while (num_literals-- > 0) {
101                history[pos++] = bytestream2_get_byte(gb);
102                if (pos == HISTORY_SIZE) {
103                    bytestream2_put_buffer(pb, history, HISTORY_SIZE);
104                    pos = 0;
105                }
106            }
107        }
108
109        if (bytestream2_get_bytes_left(gb) <= 0)
110            break;
111
112        delta = bytestream2_get_le16(gb);
113        if (delta == 0)
114            return 0;
115        match_length = 4 + (token & 0x0F);
116        if (match_length == 4 + 0x0F) {
117            uint8_t current;
118
119            do {
120                current = bytestream2_get_byte(gb);
121                match_length += current;
122            } while (current == 255);
123        }
124        reference_pos = (pos >= delta) ? (pos - delta) : (HISTORY_SIZE + pos - delta);
125        if (pos + match_length < HISTORY_SIZE && reference_pos + match_length < HISTORY_SIZE) {
126            if (pos >= reference_pos + match_length || reference_pos >= pos + match_length) {
127                memcpy(history + pos, history + reference_pos, match_length);
128                pos += match_length;
129            } else {
130                while (match_length-- > 0)
131                    history[pos++] = history[reference_pos++];
132            }
133        } else {
134            while (match_length-- > 0) {
135                history[pos++] = history[reference_pos++];
136                if (pos == HISTORY_SIZE) {
137                    bytestream2_put_buffer(pb, history, HISTORY_SIZE);
138                    pos = 0;
139                }
140                reference_pos %= HISTORY_SIZE;
141            }
142        }
143    }
144
145    bytestream2_put_buffer(pb, history, pos);
146
147    return bytestream2_tell_p(pb);
148}
149
150static int decode_blocks(AVCodecContext *avctx, AVFrame *p,
151                         unsigned uncompressed_size)
152{
153    NotchLCContext *s = avctx->priv_data;
154    GetByteContext rgb, dgb, *gb = &s->gb;
155    GetBitContext bit;
156    int ylinesize, ulinesize, vlinesize, alinesize;
157    uint16_t *dsty, *dstu, *dstv, *dsta;
158    int ret;
159
160    s->texture_size_x = bytestream2_get_le32(gb);
161    s->texture_size_y = bytestream2_get_le32(gb);
162
163    ret = ff_set_dimensions(avctx, s->texture_size_x, s->texture_size_y);
164    if (ret < 0)
165        return ret;
166
167    s->uv_offset_data_offset = bytestream2_get_le32(gb);
168    if (s->uv_offset_data_offset >= UINT_MAX / 4)
169        return AVERROR_INVALIDDATA;
170    s->uv_offset_data_offset *= 4;
171    if (s->uv_offset_data_offset >= uncompressed_size)
172        return AVERROR_INVALIDDATA;
173
174    s->y_control_data_offset = bytestream2_get_le32(gb);
175    if (s->y_control_data_offset >= UINT_MAX / 4)
176        return AVERROR_INVALIDDATA;
177    s->y_control_data_offset *= 4;
178    if (s->y_control_data_offset >= uncompressed_size)
179        return AVERROR_INVALIDDATA;
180
181    s->a_control_word_offset = bytestream2_get_le32(gb);
182    if (s->a_control_word_offset >= UINT_MAX / 4)
183        return AVERROR_INVALIDDATA;
184    s->a_control_word_offset *= 4;
185    if (s->a_control_word_offset >= uncompressed_size)
186        return AVERROR_INVALIDDATA;
187
188    s->uv_data_offset = bytestream2_get_le32(gb);
189    if (s->uv_data_offset >= UINT_MAX / 4)
190        return AVERROR_INVALIDDATA;
191    s->uv_data_offset *= 4;
192    if (s->uv_data_offset >= uncompressed_size)
193        return AVERROR_INVALIDDATA;
194
195    s->y_data_size = bytestream2_get_le32(gb);
196    if (s->y_data_size >= UINT_MAX / 4)
197        return AVERROR_INVALIDDATA;
198
199    s->a_data_offset = bytestream2_get_le32(gb);
200    if (s->a_data_offset >= UINT_MAX / 4)
201        return AVERROR_INVALIDDATA;
202    s->a_data_offset *= 4;
203    if (s->a_data_offset >= uncompressed_size)
204        return AVERROR_INVALIDDATA;
205
206    s->a_count_size = bytestream2_get_le32(gb);
207    if (s->a_count_size >= UINT_MAX / 4)
208        return AVERROR_INVALIDDATA;
209    s->a_count_size *= 4;
210    if (s->a_count_size >= uncompressed_size)
211        return AVERROR_INVALIDDATA;
212
213    s->data_end = bytestream2_get_le32(gb);
214    if (s->data_end > uncompressed_size)
215        return AVERROR_INVALIDDATA;
216
217    s->y_data_row_offsets = bytestream2_tell(gb);
218    if (s->data_end <= s->y_data_size)
219        return AVERROR_INVALIDDATA;
220    s->y_data_offset = s->data_end - s->y_data_size;
221    if (s->y_data_offset <= s->a_data_offset)
222        return AVERROR_INVALIDDATA;
223    s->uv_count_offset = s->y_data_offset - s->a_data_offset;
224
225    if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
226        return ret;
227
228    rgb = *gb;
229    dgb = *gb;
230    bytestream2_seek(&rgb, s->y_data_row_offsets, SEEK_SET);
231    bytestream2_seek(gb, s->y_control_data_offset, SEEK_SET);
232
233    if (bytestream2_get_bytes_left(gb) < (avctx->height + 3) / 4 * ((avctx->width + 3) / 4) * 4)
234        return AVERROR_INVALIDDATA;
235
236    dsty = (uint16_t *)p->data[0];
237    dsta = (uint16_t *)p->data[3];
238    ylinesize = p->linesize[0] / 2;
239    alinesize = p->linesize[3] / 2;
240
241    for (int y = 0; y < avctx->height; y += 4) {
242        const unsigned row_offset = bytestream2_get_le32(&rgb);
243
244        bytestream2_seek(&dgb, s->y_data_offset + row_offset, SEEK_SET);
245
246        init_get_bits8(&bit, dgb.buffer, bytestream2_get_bytes_left(&dgb));
247        for (int x = 0; x < avctx->width; x += 4) {
248            unsigned item = bytestream2_get_le32(gb);
249            unsigned y_min = item & 4095;
250            unsigned y_max = (item >> 12) & 4095;
251            unsigned y_diff = y_max - y_min;
252            unsigned control[4];
253
254            control[0] = (item >> 24) & 3;
255            control[1] = (item >> 26) & 3;
256            control[2] = (item >> 28) & 3;
257            control[3] = (item >> 30) & 3;
258
259            for (int i = 0; i < 4; i++) {
260                const int nb_bits = control[i] + 1;
261                const int div = (1 << nb_bits) - 1;
262                const int add = div - 1;
263
264                dsty[x + i * ylinesize + 0] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12);
265                dsty[x + i * ylinesize + 1] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12);
266                dsty[x + i * ylinesize + 2] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12);
267                dsty[x + i * ylinesize + 3] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12);
268            }
269        }
270
271        dsty += 4 * ylinesize;
272    }
273
274    rgb = *gb;
275    dgb = *gb;
276    bytestream2_seek(gb, s->a_control_word_offset, SEEK_SET);
277    if (s->uv_count_offset == s->a_control_word_offset) {
278        for (int y = 0; y < avctx->height; y++) {
279            for (int x = 0; x < avctx->width; x++)
280                dsta[x] = 4095;
281            dsta += alinesize;
282        }
283    } else {
284        if (bytestream2_get_bytes_left(gb) < (avctx->height + 15) / 16 * ((avctx->width + 15) / 16) * 8)
285            return AVERROR_INVALIDDATA;
286
287        for (int y = 0; y < avctx->height; y += 16) {
288            for (int x = 0; x < avctx->width; x += 16) {
289                unsigned m = bytestream2_get_le32(gb);
290                unsigned offset = bytestream2_get_le32(gb);
291                unsigned alpha0, alpha1;
292                uint64_t control;
293
294                if (offset >= UINT_MAX / 4)
295                    return AVERROR_INVALIDDATA;
296                offset = offset * 4 + s->uv_data_offset + s->a_data_offset;
297                if (offset >= s->data_end)
298                    return AVERROR_INVALIDDATA;
299
300                bytestream2_seek(&dgb, offset, SEEK_SET);
301                control = bytestream2_get_le64(&dgb);
302                alpha0 = control & 0xFF;
303                alpha1 = (control >> 8) & 0xFF;
304                control = control >> 16;
305
306                for (int by = 0; by < 4; by++) {
307                    for (int bx = 0; bx < 4; bx++) {
308                        switch (m & 3) {
309                        case 0:
310                            for (int i = 0; i < 4; i++) {
311                                for (int j = 0; j < 4; j++) {
312                                    dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = 0;
313                                }
314                            }
315                            break;
316                        case 1:
317                            for (int i = 0; i < 4; i++) {
318                                for (int j = 0; j < 4; j++) {
319                                    dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = 4095;
320                                }
321                            }
322                            break;
323                        case 2:
324                            for (int i = 0; i < 4; i++) {
325                                for (int j = 0; j < 4; j++) {
326                                    dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = (alpha0 + (alpha1 - alpha0) * (control & 7)) << 4;
327                                }
328                            }
329                            break;
330                        default:
331                            return AVERROR_INVALIDDATA;
332                        }
333
334                        control >>= 3;
335                        m >>= 2;
336                    }
337                }
338            }
339
340            dsta += 16 * alinesize;
341        }
342    }
343
344    bytestream2_seek(&rgb, s->uv_offset_data_offset, SEEK_SET);
345
346    dstu = (uint16_t *)p->data[1];
347    dstv = (uint16_t *)p->data[2];
348    ulinesize = p->linesize[1] / 2;
349    vlinesize = p->linesize[2] / 2;
350
351    for (int y = 0; y < avctx->height; y += 16) {
352        for (int x = 0; x < avctx->width; x += 16) {
353            unsigned offset = bytestream2_get_le32(&rgb) * 4;
354            int u[16][16] = { 0 }, v[16][16] = { 0 };
355            int u0, v0, u1, v1, udif, vdif;
356            unsigned escape, is8x8, loc;
357
358            bytestream2_seek(&dgb, s->uv_data_offset + offset, SEEK_SET);
359
360            is8x8 = bytestream2_get_le16(&dgb);
361            escape = bytestream2_get_le16(&dgb);
362
363            if (escape == 0 && is8x8 == 0) {
364                u0 = bytestream2_get_byte(&dgb);
365                v0 = bytestream2_get_byte(&dgb);
366                u1 = bytestream2_get_byte(&dgb);
367                v1 = bytestream2_get_byte(&dgb);
368                loc = bytestream2_get_le32(&dgb);
369                u0 = (u0 << 4) | (u0 & 0xF);
370                v0 = (v0 << 4) | (v0 & 0xF);
371                u1 = (u1 << 4) | (u1 & 0xF);
372                v1 = (v1 << 4) | (v1 & 0xF);
373                udif = u1 - u0;
374                vdif = v1 - v0;
375
376                for (int i = 0; i < 16; i += 4) {
377                    for (int j = 0; j < 16; j += 4) {
378                        for (int ii = 0; ii < 4; ii++) {
379                            for (int jj = 0; jj < 4; jj++) {
380                                u[i + ii][j + jj] = u0 + ((udif * (int)(loc & 3) + 2) / 3);
381                                v[i + ii][j + jj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3);
382                            }
383                        }
384
385                        loc >>= 2;
386                    }
387                }
388            } else {
389                for (int i = 0; i < 16; i += 8) {
390                    for (int j = 0; j < 16; j += 8) {
391                        if (is8x8 & 1) {
392                            u0 = bytestream2_get_byte(&dgb);
393                            v0 = bytestream2_get_byte(&dgb);
394                            u1 = bytestream2_get_byte(&dgb);
395                            v1 = bytestream2_get_byte(&dgb);
396                            loc = bytestream2_get_le32(&dgb);
397                            u0 = (u0 << 4) | (u0 & 0xF);
398                            v0 = (v0 << 4) | (v0 & 0xF);
399                            u1 = (u1 << 4) | (u1 & 0xF);
400                            v1 = (v1 << 4) | (v1 & 0xF);
401                            udif = u1 - u0;
402                            vdif = v1 - v0;
403
404                            for (int ii = 0; ii < 8; ii += 2) {
405                                for (int jj = 0; jj < 8; jj += 2) {
406                                    for (int iii = 0; iii < 2; iii++) {
407                                        for (int jjj = 0; jjj < 2; jjj++) {
408                                            u[i + ii + iii][j + jj + jjj] = u0 + ((udif * (int)(loc & 3) + 2) / 3);
409                                            v[i + ii + iii][j + jj + jjj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3);
410                                        }
411                                    }
412
413                                    loc >>= 2;
414                                }
415                            }
416                        } else if (escape) {
417                            for (int ii = 0; ii < 8; ii += 4) {
418                                for (int jj = 0; jj < 8; jj += 4) {
419                                    u0 = bytestream2_get_byte(&dgb);
420                                    v0 = bytestream2_get_byte(&dgb);
421                                    u1 = bytestream2_get_byte(&dgb);
422                                    v1 = bytestream2_get_byte(&dgb);
423                                    loc = bytestream2_get_le32(&dgb);
424                                    u0 = (u0 << 4) | (u0 & 0xF);
425                                    v0 = (v0 << 4) | (v0 & 0xF);
426                                    u1 = (u1 << 4) | (u1 & 0xF);
427                                    v1 = (v1 << 4) | (v1 & 0xF);
428                                    udif = u1 - u0;
429                                    vdif = v1 - v0;
430
431                                    for (int iii = 0; iii < 4; iii++) {
432                                        for (int jjj = 0; jjj < 4; jjj++) {
433                                            u[i + ii + iii][j + jj + jjj] = u0 + ((udif * (int)(loc & 3) + 2) / 3);
434                                            v[i + ii + iii][j + jj + jjj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3);
435
436                                            loc >>= 2;
437                                        }
438                                    }
439                                }
440                            }
441                        }
442
443                        is8x8 >>= 1;
444                    }
445                }
446            }
447
448            for (int i = 0; i < 16; i++) {
449                for (int j = 0; j < 16; j++) {
450                    dstu[x + i * ulinesize + j] = u[i][j];
451                    dstv[x + i * vlinesize + j] = v[i][j];
452                }
453            }
454        }
455
456        dstu += 16 * ulinesize;
457        dstv += 16 * vlinesize;
458    }
459
460    return 0;
461}
462
463static int decode_frame(AVCodecContext *avctx, AVFrame *p,
464                        int *got_frame, AVPacket *avpkt)
465{
466    NotchLCContext *s = avctx->priv_data;
467    GetByteContext *gb = &s->gb;
468    PutByteContext *pb = &s->pb;
469    unsigned uncompressed_size;
470    int ret;
471
472    if (avpkt->size <= 40)
473        return AVERROR_INVALIDDATA;
474
475    bytestream2_init(gb, avpkt->data, avpkt->size);
476
477    if (bytestream2_get_le32(gb) != MKBETAG('N','L','C','1'))
478        return AVERROR_INVALIDDATA;
479
480    uncompressed_size = bytestream2_get_le32(gb);
481    s->compressed_size = bytestream2_get_le32(gb);
482    s->format = bytestream2_get_le32(gb);
483
484    if (s->format > 2)
485        return AVERROR_PATCHWELCOME;
486
487    if (s->format == 0) {
488        ret = ff_lzf_uncompress(gb, &s->lzf_buffer, &s->lzf_size);
489        if (ret < 0)
490            return ret;
491
492        if (uncompressed_size > s->lzf_size)
493            return AVERROR_INVALIDDATA;
494
495        bytestream2_init(gb, s->lzf_buffer, uncompressed_size);
496    } else if (s->format == 1) {
497        if (bytestream2_get_bytes_left(gb) < uncompressed_size / 255)
498            return AVERROR_INVALIDDATA;
499
500        av_fast_padded_malloc(&s->uncompressed_buffer, &s->uncompressed_size,
501                              uncompressed_size);
502        if (!s->uncompressed_buffer)
503            return AVERROR(ENOMEM);
504
505        bytestream2_init_writer(pb, s->uncompressed_buffer, s->uncompressed_size);
506
507        ret = lz4_decompress(avctx, gb, pb);
508        if (ret != uncompressed_size)
509            return AVERROR_INVALIDDATA;
510
511        bytestream2_init(gb, s->uncompressed_buffer, uncompressed_size);
512    }
513
514    ret = decode_blocks(avctx, p, uncompressed_size);
515    if (ret < 0)
516        return ret;
517
518    p->pict_type = AV_PICTURE_TYPE_I;
519    p->key_frame = 1;
520
521    *got_frame = 1;
522
523    return avpkt->size;
524}
525
526static av_cold int decode_end(AVCodecContext *avctx)
527{
528    NotchLCContext *s = avctx->priv_data;
529
530    av_freep(&s->uncompressed_buffer);
531    s->uncompressed_size = 0;
532    av_freep(&s->lzf_buffer);
533    s->lzf_size = 0;
534
535    return 0;
536}
537
538const FFCodec ff_notchlc_decoder = {
539    .p.name           = "notchlc",
540    .p.long_name      = NULL_IF_CONFIG_SMALL("NotchLC"),
541    .p.type           = AVMEDIA_TYPE_VIDEO,
542    .p.id             = AV_CODEC_ID_NOTCHLC,
543    .priv_data_size   = sizeof(NotchLCContext),
544    .init             = decode_init,
545    .close            = decode_end,
546    FF_CODEC_DECODE_CB(decode_frame),
547    .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
548    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE,
549};
550