• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
36 typedef 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 
decode_init(AVCodecContext * avctx)64 static 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 
lz4_decompress(AVCodecContext * avctx,GetByteContext * gb,PutByteContext * pb)77 static 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 
decode_blocks(AVCodecContext * avctx,AVFrame * p,unsigned uncompressed_size)150 static 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 
decode_frame(AVCodecContext * avctx,AVFrame * p,int * got_frame,AVPacket * avpkt)463 static 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 
decode_end(AVCodecContext * avctx)526 static 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 
538 const 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