xref: /third_party/ffmpeg/libavcodec/cllc.c (revision cabdff1a)
1/*
2 * Canopus Lossless Codec decoder
3 *
4 * Copyright (c) 2012-2013 Derek Buitenhuis
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <inttypes.h>
24
25#include "libavutil/intreadwrite.h"
26#include "bswapdsp.h"
27#include "canopus.h"
28#include "get_bits.h"
29#include "avcodec.h"
30#include "codec_internal.h"
31#include "thread.h"
32
33#define VLC_BITS 7
34#define VLC_DEPTH 2
35
36
37typedef struct CLLCContext {
38    AVCodecContext *avctx;
39    BswapDSPContext bdsp;
40
41    uint8_t *swapped_buf;
42    int      swapped_buf_size;
43} CLLCContext;
44
45static int read_code_table(CLLCContext *ctx, GetBitContext *gb, VLC *vlc)
46{
47    uint8_t symbols[256];
48    uint8_t bits[256];
49    int num_lens, num_codes, num_codes_sum;
50    int i, j, count;
51
52    count         = 0;
53    num_codes_sum = 0;
54
55    num_lens = get_bits(gb, 5);
56
57    if (num_lens > VLC_BITS * VLC_DEPTH) {
58        av_log(ctx->avctx, AV_LOG_ERROR, "To long VLCs %d\n", num_lens);
59        return AVERROR_INVALIDDATA;
60    }
61
62    for (i = 0; i < num_lens; i++) {
63        num_codes      = get_bits(gb, 9);
64        num_codes_sum += num_codes;
65
66        if (num_codes_sum > 256) {
67            av_log(ctx->avctx, AV_LOG_ERROR,
68                   "Too many VLCs (%d) to be read.\n", num_codes_sum);
69            return AVERROR_INVALIDDATA;
70        }
71
72        for (j = 0; j < num_codes; j++) {
73            symbols[count] = get_bits(gb, 8);
74            bits[count]    = i + 1;
75
76            count++;
77        }
78    }
79
80    return ff_init_vlc_from_lengths(vlc, VLC_BITS, count, bits, 1,
81                                    symbols, 1, 1, 0, 0, ctx->avctx);
82}
83
84/*
85 * Unlike the RGB24 read/restore, which reads in a component at a time,
86 * ARGB read/restore reads in ARGB quads.
87 */
88static int read_argb_line(CLLCContext *ctx, GetBitContext *gb, int *top_left,
89                          VLC *vlc, uint8_t *outbuf)
90{
91    uint8_t *dst;
92    int pred[4];
93    int code;
94    int i;
95
96    OPEN_READER(bits, gb);
97
98    dst     = outbuf;
99    pred[0] = top_left[0];
100    pred[1] = top_left[1];
101    pred[2] = top_left[2];
102    pred[3] = top_left[3];
103
104    for (i = 0; i < ctx->avctx->width; i++) {
105        /* Always get the alpha component */
106        UPDATE_CACHE(bits, gb);
107        GET_VLC(code, bits, gb, vlc[0].table, VLC_BITS, VLC_DEPTH);
108
109        pred[0] += code;
110        dst[0]   = pred[0];
111
112        /* Skip the components if they are  entirely transparent */
113        if (dst[0]) {
114            /* Red */
115            UPDATE_CACHE(bits, gb);
116            GET_VLC(code, bits, gb, vlc[1].table, VLC_BITS, VLC_DEPTH);
117
118            pred[1] += code;
119            dst[1]   = pred[1];
120
121            /* Green */
122            UPDATE_CACHE(bits, gb);
123            GET_VLC(code, bits, gb, vlc[2].table, VLC_BITS, VLC_DEPTH);
124
125            pred[2] += code;
126            dst[2]   = pred[2];
127
128            /* Blue */
129            UPDATE_CACHE(bits, gb);
130            GET_VLC(code, bits, gb, vlc[3].table, VLC_BITS, VLC_DEPTH);
131
132            pred[3] += code;
133            dst[3]   = pred[3];
134        } else {
135            dst[1] = 0;
136            dst[2] = 0;
137            dst[3] = 0;
138        }
139
140        dst += 4;
141    }
142
143    CLOSE_READER(bits, gb);
144
145    top_left[0]  = outbuf[0];
146
147    /* Only stash components if they are not transparent */
148    if (top_left[0]) {
149        top_left[1] = outbuf[1];
150        top_left[2] = outbuf[2];
151        top_left[3] = outbuf[3];
152    }
153
154    return 0;
155}
156
157static int read_rgb24_component_line(CLLCContext *ctx, GetBitContext *gb,
158                                     int *top_left, VLC *vlc, uint8_t *outbuf)
159{
160    uint8_t *dst;
161    int pred, code;
162    int i;
163
164    OPEN_READER(bits, gb);
165
166    dst  = outbuf;
167    pred = *top_left;
168
169    /* Simultaneously read and restore the line */
170    for (i = 0; i < ctx->avctx->width; i++) {
171        UPDATE_CACHE(bits, gb);
172        GET_VLC(code, bits, gb, vlc->table, VLC_BITS, VLC_DEPTH);
173
174        pred  += code;
175        dst[0] = pred;
176        dst   += 3;
177    }
178
179    CLOSE_READER(bits, gb);
180
181    /* Stash the first pixel */
182    *top_left = outbuf[0];
183
184    return 0;
185}
186
187static int read_yuv_component_line(CLLCContext *ctx, GetBitContext *gb,
188                                   int *top_left, VLC *vlc, uint8_t *outbuf,
189                                   int is_chroma)
190{
191    int pred, code;
192    int i;
193
194    OPEN_READER(bits, gb);
195
196    pred = *top_left;
197
198    /* Simultaneously read and restore the line */
199    for (i = 0; i < ctx->avctx->width >> is_chroma; i++) {
200        UPDATE_CACHE(bits, gb);
201        GET_VLC(code, bits, gb, vlc->table, VLC_BITS, VLC_DEPTH);
202
203        pred     += code;
204        outbuf[i] = pred;
205    }
206
207    CLOSE_READER(bits, gb);
208
209    /* Stash the first pixel */
210    *top_left = outbuf[0];
211
212    return 0;
213}
214
215static int decode_argb_frame(CLLCContext *ctx, GetBitContext *gb, AVFrame *pic)
216{
217    AVCodecContext *avctx = ctx->avctx;
218    uint8_t *dst;
219    int pred[4];
220    int ret;
221    int i, j;
222    VLC vlc[4];
223
224    pred[0] = 0;
225    pred[1] = 0x80;
226    pred[2] = 0x80;
227    pred[3] = 0x80;
228
229    dst = pic->data[0];
230
231    skip_bits(gb, 16);
232
233    /* Read in code table for each plane */
234    for (i = 0; i < 4; i++) {
235        ret = read_code_table(ctx, gb, &vlc[i]);
236        if (ret < 0) {
237            for (j = 0; j < i; j++)
238                ff_free_vlc(&vlc[j]);
239
240            av_log(ctx->avctx, AV_LOG_ERROR,
241                   "Could not read code table %d.\n", i);
242            return ret;
243        }
244    }
245
246    /* Read in and restore every line */
247    for (i = 0; i < avctx->height; i++) {
248        read_argb_line(ctx, gb, pred, vlc, dst);
249
250        dst += pic->linesize[0];
251    }
252
253    for (i = 0; i < 4; i++)
254        ff_free_vlc(&vlc[i]);
255
256    return 0;
257}
258
259static int decode_rgb24_frame(CLLCContext *ctx, GetBitContext *gb, AVFrame *pic)
260{
261    AVCodecContext *avctx = ctx->avctx;
262    uint8_t *dst;
263    int pred[3];
264    int ret;
265    int i, j;
266    VLC vlc[3];
267
268    pred[0] = 0x80;
269    pred[1] = 0x80;
270    pred[2] = 0x80;
271
272    dst = pic->data[0];
273
274    skip_bits(gb, 16);
275
276    /* Read in code table for each plane */
277    for (i = 0; i < 3; i++) {
278        ret = read_code_table(ctx, gb, &vlc[i]);
279        if (ret < 0) {
280            for (j = 0; j < i; j++)
281                ff_free_vlc(&vlc[j]);
282
283            av_log(ctx->avctx, AV_LOG_ERROR,
284                   "Could not read code table %d.\n", i);
285            return ret;
286        }
287    }
288
289    /* Read in and restore every line */
290    for (i = 0; i < avctx->height; i++) {
291        for (j = 0; j < 3; j++)
292            read_rgb24_component_line(ctx, gb, &pred[j], &vlc[j], &dst[j]);
293
294        dst += pic->linesize[0];
295    }
296
297    for (i = 0; i < 3; i++)
298        ff_free_vlc(&vlc[i]);
299
300    return 0;
301}
302
303static int decode_yuv_frame(CLLCContext *ctx, GetBitContext *gb, AVFrame *pic)
304{
305    AVCodecContext *avctx = ctx->avctx;
306    uint8_t block;
307    uint8_t *dst[3];
308    int pred[3];
309    int ret;
310    int i, j;
311    VLC vlc[2];
312
313    pred[0] = 0x80;
314    pred[1] = 0x80;
315    pred[2] = 0x80;
316
317    dst[0] = pic->data[0];
318    dst[1] = pic->data[1];
319    dst[2] = pic->data[2];
320
321    skip_bits(gb, 8);
322
323    block = get_bits(gb, 8);
324    if (block) {
325        avpriv_request_sample(ctx->avctx, "Blocked YUV");
326        return AVERROR_PATCHWELCOME;
327    }
328
329    /* Read in code table for luma and chroma */
330    for (i = 0; i < 2; i++) {
331        ret = read_code_table(ctx, gb, &vlc[i]);
332        if (ret < 0) {
333            for (j = 0; j < i; j++)
334                ff_free_vlc(&vlc[j]);
335
336            av_log(ctx->avctx, AV_LOG_ERROR,
337                   "Could not read code table %d.\n", i);
338            return ret;
339        }
340    }
341
342    /* Read in and restore every line */
343    for (i = 0; i < avctx->height; i++) {
344        read_yuv_component_line(ctx, gb, &pred[0], &vlc[0], dst[0], 0); /* Y */
345        read_yuv_component_line(ctx, gb, &pred[1], &vlc[1], dst[1], 1); /* U */
346        read_yuv_component_line(ctx, gb, &pred[2], &vlc[1], dst[2], 1); /* V */
347
348        for (j = 0; j < 3; j++)
349            dst[j] += pic->linesize[j];
350    }
351
352    for (i = 0; i < 2; i++)
353        ff_free_vlc(&vlc[i]);
354
355    return 0;
356}
357
358static int cllc_decode_frame(AVCodecContext *avctx, AVFrame *pic,
359                             int *got_picture_ptr, AVPacket *avpkt)
360{
361    CLLCContext *ctx = avctx->priv_data;
362    const uint8_t *src = avpkt->data;
363    uint32_t info_tag, info_offset;
364    int data_size;
365    GetBitContext gb;
366    int coding_type, ret;
367
368    if (avpkt->size < 4 + 4) {
369        av_log(avctx, AV_LOG_ERROR, "Frame is too small %d.\n", avpkt->size);
370        return AVERROR_INVALIDDATA;
371    }
372
373    info_offset = 0;
374    info_tag    = AV_RL32(src);
375    if (info_tag == MKTAG('I', 'N', 'F', 'O')) {
376        info_offset = AV_RL32(src + 4);
377        if (info_offset > UINT32_MAX - 8 || info_offset + 8 > avpkt->size) {
378            av_log(avctx, AV_LOG_ERROR,
379                   "Invalid INFO header offset: 0x%08"PRIX32" is too large.\n",
380                   info_offset);
381            return AVERROR_INVALIDDATA;
382        }
383        ff_canopus_parse_info_tag(avctx, src + 8, info_offset);
384
385        info_offset += 8;
386        src         += info_offset;
387    }
388
389    data_size = (avpkt->size - info_offset) & ~1;
390
391    /* Make sure our bswap16'd buffer is big enough */
392    av_fast_padded_malloc(&ctx->swapped_buf,
393                          &ctx->swapped_buf_size, data_size);
394    if (!ctx->swapped_buf) {
395        av_log(avctx, AV_LOG_ERROR, "Could not allocate swapped buffer.\n");
396        return AVERROR(ENOMEM);
397    }
398
399    /* bswap16 the buffer since CLLC's bitreader works in 16-bit words */
400    ctx->bdsp.bswap16_buf((uint16_t *) ctx->swapped_buf, (uint16_t *) src,
401                          data_size / 2);
402
403    if ((ret = init_get_bits8(&gb, ctx->swapped_buf, data_size)) < 0)
404        return ret;
405
406    /*
407     * Read in coding type. The types are as follows:
408     *
409     * 0 - YUY2
410     * 1 - BGR24 (Triples)
411     * 2 - BGR24 (Quads)
412     * 3 - BGRA
413     */
414    coding_type = (AV_RL32(src) >> 8) & 0xFF;
415    av_log(avctx, AV_LOG_DEBUG, "Frame coding type: %d\n", coding_type);
416
417    if(get_bits_left(&gb) < avctx->height * avctx->width)
418        return AVERROR_INVALIDDATA;
419
420    switch (coding_type) {
421    case 0:
422        avctx->pix_fmt             = AV_PIX_FMT_YUV422P;
423        avctx->bits_per_raw_sample = 8;
424
425        if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
426            return ret;
427
428        ret = decode_yuv_frame(ctx, &gb, pic);
429        if (ret < 0)
430            return ret;
431
432        break;
433    case 1:
434    case 2:
435        avctx->pix_fmt             = AV_PIX_FMT_RGB24;
436        avctx->bits_per_raw_sample = 8;
437
438        if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
439            return ret;
440
441        ret = decode_rgb24_frame(ctx, &gb, pic);
442        if (ret < 0)
443            return ret;
444
445        break;
446    case 3:
447        avctx->pix_fmt             = AV_PIX_FMT_ARGB;
448        avctx->bits_per_raw_sample = 8;
449
450        if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
451            return ret;
452
453        ret = decode_argb_frame(ctx, &gb, pic);
454        if (ret < 0)
455            return ret;
456
457        break;
458    default:
459        av_log(avctx, AV_LOG_ERROR, "Unknown coding type: %d.\n", coding_type);
460        return AVERROR_INVALIDDATA;
461    }
462
463    pic->key_frame = 1;
464    pic->pict_type = AV_PICTURE_TYPE_I;
465
466    *got_picture_ptr = 1;
467
468    return avpkt->size;
469}
470
471static av_cold int cllc_decode_close(AVCodecContext *avctx)
472{
473    CLLCContext *ctx = avctx->priv_data;
474
475    av_freep(&ctx->swapped_buf);
476
477    return 0;
478}
479
480static av_cold int cllc_decode_init(AVCodecContext *avctx)
481{
482    CLLCContext *ctx = avctx->priv_data;
483
484    /* Initialize various context values */
485    ctx->avctx            = avctx;
486    ctx->swapped_buf      = NULL;
487    ctx->swapped_buf_size = 0;
488
489    ff_bswapdsp_init(&ctx->bdsp);
490
491    return 0;
492}
493
494const FFCodec ff_cllc_decoder = {
495    .p.name         = "cllc",
496    .p.long_name    = NULL_IF_CONFIG_SMALL("Canopus Lossless Codec"),
497    .p.type         = AVMEDIA_TYPE_VIDEO,
498    .p.id           = AV_CODEC_ID_CLLC,
499    .priv_data_size = sizeof(CLLCContext),
500    .init           = cllc_decode_init,
501    FF_CODEC_DECODE_CB(cllc_decode_frame),
502    .close          = cllc_decode_close,
503    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
504    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
505};
506