LCOV - code coverage report
Current view: top level - libavcodec - utvideodec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 367 660 55.6 %
Date: 2018-02-24 03:21:38 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /*
       2             :  * Ut Video decoder
       3             :  * Copyright (c) 2011 Konstantin Shishkov
       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             : /**
      23             :  * @file
      24             :  * Ut Video decoder
      25             :  */
      26             : 
      27             : #include <inttypes.h>
      28             : #include <stdlib.h>
      29             : 
      30             : #define UNCHECKED_BITSTREAM_READER 1
      31             : 
      32             : #include "libavutil/intreadwrite.h"
      33             : #include "avcodec.h"
      34             : #include "bswapdsp.h"
      35             : #include "bytestream.h"
      36             : #include "get_bits.h"
      37             : #include "internal.h"
      38             : #include "thread.h"
      39             : #include "utvideo.h"
      40             : 
      41           0 : static int build_huff10(const uint8_t *src, VLC *vlc, int *fsym)
      42             : {
      43             :     int i;
      44             :     HuffEntry he[1024];
      45             :     int last;
      46             :     uint32_t codes[1024];
      47             :     uint8_t bits[1024];
      48             :     uint16_t syms[1024];
      49             :     uint32_t code;
      50             : 
      51           0 :     *fsym = -1;
      52           0 :     for (i = 0; i < 1024; i++) {
      53           0 :         he[i].sym = i;
      54           0 :         he[i].len = *src++;
      55             :     }
      56           0 :     qsort(he, 1024, sizeof(*he), ff_ut10_huff_cmp_len);
      57             : 
      58           0 :     if (!he[0].len) {
      59           0 :         *fsym = he[0].sym;
      60           0 :         return 0;
      61             :     }
      62             : 
      63           0 :     last = 1023;
      64           0 :     while (he[last].len == 255 && last)
      65           0 :         last--;
      66             : 
      67           0 :     if (he[last].len > 32) {
      68           0 :         return -1;
      69             :     }
      70             : 
      71           0 :     code = 1;
      72           0 :     for (i = last; i >= 0; i--) {
      73           0 :         codes[i] = code >> (32 - he[i].len);
      74           0 :         bits[i]  = he[i].len;
      75           0 :         syms[i]  = he[i].sym;
      76           0 :         code += 0x80000000u >> (he[i].len - 1);
      77             :     }
      78             : #define VLC_BITS 11
      79           0 :     return ff_init_vlc_sparse(vlc, VLC_BITS, last + 1,
      80             :                               bits,  sizeof(*bits),  sizeof(*bits),
      81             :                               codes, sizeof(*codes), sizeof(*codes),
      82             :                               syms,  sizeof(*syms),  sizeof(*syms), 0);
      83             : }
      84             : 
      85         183 : static int build_huff(const uint8_t *src, VLC *vlc, int *fsym)
      86             : {
      87             :     int i;
      88             :     HuffEntry he[256];
      89             :     int last;
      90             :     uint32_t codes[256];
      91             :     uint8_t bits[256];
      92             :     uint8_t syms[256];
      93             :     uint32_t code;
      94             : 
      95         183 :     *fsym = -1;
      96       47031 :     for (i = 0; i < 256; i++) {
      97       46848 :         he[i].sym = i;
      98       46848 :         he[i].len = *src++;
      99             :     }
     100         183 :     qsort(he, 256, sizeof(*he), ff_ut_huff_cmp_len);
     101             : 
     102         183 :     if (!he[0].len) {
     103           4 :         *fsym = he[0].sym;
     104           4 :         return 0;
     105             :     }
     106             : 
     107         179 :     last = 255;
     108       18429 :     while (he[last].len == 255 && last)
     109       18071 :         last--;
     110             : 
     111         179 :     if (he[last].len > 32)
     112           0 :         return -1;
     113             : 
     114         179 :     code = 1;
     115       27932 :     for (i = last; i >= 0; i--) {
     116       27753 :         codes[i] = code >> (32 - he[i].len);
     117       27753 :         bits[i]  = he[i].len;
     118       27753 :         syms[i]  = he[i].sym;
     119       27753 :         code += 0x80000000u >> (he[i].len - 1);
     120             :     }
     121             : 
     122         179 :     return ff_init_vlc_sparse(vlc, VLC_BITS, last + 1,
     123             :                               bits,  sizeof(*bits),  sizeof(*bits),
     124             :                               codes, sizeof(*codes), sizeof(*codes),
     125             :                               syms,  sizeof(*syms),  sizeof(*syms), 0);
     126             : }
     127             : 
     128           0 : static int decode_plane10(UtvideoContext *c, int plane_no,
     129             :                           uint16_t *dst, ptrdiff_t stride,
     130             :                           int width, int height,
     131             :                           const uint8_t *src, const uint8_t *huff,
     132             :                           int use_pred)
     133             : {
     134             :     int i, j, slice, pix, ret;
     135             :     int sstart, send;
     136             :     VLC vlc;
     137             :     GetBitContext gb;
     138             :     int prev, fsym;
     139             : 
     140           0 :     if ((ret = build_huff10(huff, &vlc, &fsym)) < 0) {
     141           0 :         av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
     142           0 :         return ret;
     143             :     }
     144           0 :     if (fsym >= 0) { // build_huff reported a symbol to fill slices with
     145           0 :         send = 0;
     146           0 :         for (slice = 0; slice < c->slices; slice++) {
     147             :             uint16_t *dest;
     148             : 
     149           0 :             sstart = send;
     150           0 :             send   = (height * (slice + 1) / c->slices);
     151           0 :             dest   = dst + sstart * stride;
     152             : 
     153           0 :             prev = 0x200;
     154           0 :             for (j = sstart; j < send; j++) {
     155           0 :                 for (i = 0; i < width; i++) {
     156           0 :                     pix = fsym;
     157           0 :                     if (use_pred) {
     158           0 :                         prev += pix;
     159           0 :                         prev &= 0x3FF;
     160           0 :                         pix   = prev;
     161             :                     }
     162           0 :                     dest[i] = pix;
     163             :                 }
     164           0 :                 dest += stride;
     165             :             }
     166             :         }
     167           0 :         return 0;
     168             :     }
     169             : 
     170           0 :     send = 0;
     171           0 :     for (slice = 0; slice < c->slices; slice++) {
     172             :         uint16_t *dest;
     173             :         int slice_data_start, slice_data_end, slice_size;
     174             : 
     175           0 :         sstart = send;
     176           0 :         send   = (height * (slice + 1) / c->slices);
     177           0 :         dest   = dst + sstart * stride;
     178             : 
     179             :         // slice offset and size validation was done earlier
     180           0 :         slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0;
     181           0 :         slice_data_end   = AV_RL32(src + slice * 4);
     182           0 :         slice_size       = slice_data_end - slice_data_start;
     183             : 
     184           0 :         if (!slice_size) {
     185           0 :             av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol "
     186             :                    "yet a slice has a length of zero.\n");
     187           0 :             goto fail;
     188             :         }
     189             : 
     190           0 :         memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
     191           0 :         c->bdsp.bswap_buf((uint32_t *) c->slice_bits,
     192           0 :                           (uint32_t *)(src + slice_data_start + c->slices * 4),
     193           0 :                           (slice_data_end - slice_data_start + 3) >> 2);
     194           0 :         init_get_bits(&gb, c->slice_bits, slice_size * 8);
     195             : 
     196           0 :         prev = 0x200;
     197           0 :         for (j = sstart; j < send; j++) {
     198           0 :             for (i = 0; i < width; i++) {
     199           0 :                 pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);
     200           0 :                 if (pix < 0) {
     201           0 :                     av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
     202           0 :                     goto fail;
     203             :                 }
     204           0 :                 if (use_pred) {
     205           0 :                     prev += pix;
     206           0 :                     prev &= 0x3FF;
     207           0 :                     pix   = prev;
     208             :                 }
     209           0 :                 dest[i] = pix;
     210             :             }
     211           0 :             dest += stride;
     212           0 :             if (get_bits_left(&gb) < 0) {
     213           0 :                 av_log(c->avctx, AV_LOG_ERROR,
     214             :                         "Slice decoding ran out of bits\n");
     215           0 :                 goto fail;
     216             :             }
     217             :         }
     218           0 :         if (get_bits_left(&gb) > 32)
     219           0 :             av_log(c->avctx, AV_LOG_WARNING,
     220             :                    "%d bits left after decoding slice\n", get_bits_left(&gb));
     221             :     }
     222             : 
     223           0 :     ff_free_vlc(&vlc);
     224             : 
     225           0 :     return 0;
     226           0 : fail:
     227           0 :     ff_free_vlc(&vlc);
     228           0 :     return AVERROR_INVALIDDATA;
     229             : }
     230             : 
     231         183 : static int compute_cmask(int plane_no, int interlaced, enum AVPixelFormat pix_fmt)
     232             : {
     233         183 :     const int is_luma = (pix_fmt == AV_PIX_FMT_YUV420P) && !plane_no;
     234             : 
     235         183 :     if (interlaced)
     236          24 :         return ~(1 + 2 * is_luma);
     237             : 
     238         159 :     return ~is_luma;
     239             : }
     240             : 
     241         183 : static int decode_plane(UtvideoContext *c, int plane_no,
     242             :                         uint8_t *dst, ptrdiff_t stride,
     243             :                         int width, int height,
     244             :                         const uint8_t *src, int use_pred)
     245             : {
     246             :     int i, j, slice, pix;
     247             :     int sstart, send;
     248             :     VLC vlc;
     249             :     GetBitContext gb;
     250             :     int ret, prev, fsym;
     251         183 :     const int cmask = compute_cmask(plane_no, c->interlaced, c->avctx->pix_fmt);
     252             : 
     253         183 :     if (c->pack) {
     254           0 :         send = 0;
     255           0 :         for (slice = 0; slice < c->slices; slice++) {
     256             :             GetBitContext cbit, pbit;
     257             :             uint8_t *dest, *p;
     258             : 
     259           0 :             ret = init_get_bits8(&cbit, c->control_stream[plane_no][slice], c->control_stream_size[plane_no][slice]);
     260           0 :             if (ret < 0)
     261           0 :                 return ret;
     262             : 
     263           0 :             ret = init_get_bits8(&pbit, c->packed_stream[plane_no][slice], c->packed_stream_size[plane_no][slice]);
     264           0 :             if (ret < 0)
     265           0 :                 return ret;
     266             : 
     267           0 :             sstart = send;
     268           0 :             send   = (height * (slice + 1) / c->slices) & cmask;
     269           0 :             dest   = dst + sstart * stride;
     270             : 
     271           0 :             if (3 * ((dst + send * stride - dest + 7)/8) > get_bits_left(&cbit))
     272           0 :                 return AVERROR_INVALIDDATA;
     273             : 
     274           0 :             for (p = dest; p < dst + send * stride; p += 8) {
     275           0 :                 int bits = get_bits_le(&cbit, 3);
     276             : 
     277           0 :                 if (bits == 0) {
     278           0 :                     *(uint64_t *) p = 0;
     279             :                 } else {
     280           0 :                     uint32_t sub = 0x80 >> (8 - (bits + 1)), add;
     281             :                     int k;
     282             : 
     283           0 :                     if ((bits + 1) * 8 > get_bits_left(&pbit))
     284           0 :                         return AVERROR_INVALIDDATA;
     285             : 
     286           0 :                     for (k = 0; k < 8; k++) {
     287             : 
     288           0 :                         p[k] = get_bits_le(&pbit, bits + 1);
     289           0 :                         add = (~p[k] & sub) << (8 - bits);
     290           0 :                         p[k] -= sub;
     291           0 :                         p[k] += add;
     292             :                     }
     293             :                 }
     294             :             }
     295             :         }
     296             : 
     297           0 :         return 0;
     298             :     }
     299             : 
     300         183 :     if (build_huff(src, &vlc, &fsym)) {
     301           0 :         av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
     302           0 :         return AVERROR_INVALIDDATA;
     303             :     }
     304         183 :     if (fsym >= 0) { // build_huff reported a symbol to fill slices with
     305           4 :         send = 0;
     306          20 :         for (slice = 0; slice < c->slices; slice++) {
     307             :             uint8_t *dest;
     308             : 
     309          16 :             sstart = send;
     310          16 :             send   = (height * (slice + 1) / c->slices) & cmask;
     311          16 :             dest   = dst + sstart * stride;
     312             : 
     313          16 :             prev = 0x80;
     314        3088 :             for (j = sstart; j < send; j++) {
     315     3148800 :                 for (i = 0; i < width; i++) {
     316     3145728 :                     pix = fsym;
     317     3145728 :                     if (use_pred) {
     318           0 :                         prev += pix;
     319           0 :                         pix   = prev;
     320             :                     }
     321     3145728 :                     dest[i] = pix;
     322             :                 }
     323        3072 :                 dest += stride;
     324             :             }
     325             :         }
     326           4 :         return 0;
     327             :     }
     328             : 
     329         179 :     src      += 256;
     330             : 
     331         179 :     send = 0;
     332         895 :     for (slice = 0; slice < c->slices; slice++) {
     333             :         uint8_t *dest;
     334             :         int slice_data_start, slice_data_end, slice_size;
     335             : 
     336         716 :         sstart = send;
     337         716 :         send   = (height * (slice + 1) / c->slices) & cmask;
     338         716 :         dest   = dst + sstart * stride;
     339             : 
     340             :         // slice offset and size validation was done earlier
     341         716 :         slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0;
     342         716 :         slice_data_end   = AV_RL32(src + slice * 4);
     343         716 :         slice_size       = slice_data_end - slice_data_start;
     344             : 
     345         716 :         if (!slice_size) {
     346           0 :             av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol "
     347             :                    "yet a slice has a length of zero.\n");
     348           0 :             goto fail;
     349             :         }
     350             : 
     351         716 :         memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
     352        2148 :         c->bdsp.bswap_buf((uint32_t *) c->slice_bits,
     353         716 :                           (uint32_t *)(src + slice_data_start + c->slices * 4),
     354         716 :                           (slice_data_end - slice_data_start + 3) >> 2);
     355         716 :         init_get_bits(&gb, c->slice_bits, slice_size * 8);
     356             : 
     357         716 :         prev = 0x80;
     358       63858 :         for (j = sstart; j < send; j++) {
     359    35325686 :             for (i = 0; i < width; i++) {
     360    35262544 :                 pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);
     361    35262544 :                 if (pix < 0) {
     362           0 :                     av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
     363           0 :                     goto fail;
     364             :                 }
     365    35262544 :                 if (use_pred) {
     366    15513600 :                     prev += pix;
     367    15513600 :                     pix   = prev;
     368             :                 }
     369    35262544 :                 dest[i] = pix;
     370             :             }
     371       63142 :             if (get_bits_left(&gb) < 0) {
     372           0 :                 av_log(c->avctx, AV_LOG_ERROR,
     373             :                         "Slice decoding ran out of bits\n");
     374           0 :                 goto fail;
     375             :             }
     376       63142 :             dest += stride;
     377             :         }
     378         716 :         if (get_bits_left(&gb) > 32)
     379           0 :             av_log(c->avctx, AV_LOG_WARNING,
     380             :                    "%d bits left after decoding slice\n", get_bits_left(&gb));
     381             :     }
     382             : 
     383         179 :     ff_free_vlc(&vlc);
     384             : 
     385         179 :     return 0;
     386           0 : fail:
     387           0 :     ff_free_vlc(&vlc);
     388           0 :     return AVERROR_INVALIDDATA;
     389             : }
     390             : 
     391             : #undef A
     392             : #undef B
     393             : #undef C
     394             : 
     395          77 : static void restore_median_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
     396             :                                   int width, int height, int slices, int rmode)
     397             : {
     398             :     int i, j, slice;
     399             :     int A, B, C;
     400             :     uint8_t *bsrc;
     401             :     int slice_start, slice_height;
     402          77 :     const int cmask = ~rmode;
     403             : 
     404         385 :     for (slice = 0; slice < slices; slice++) {
     405         308 :         slice_start  = ((slice * height) / slices) & cmask;
     406         308 :         slice_height = ((((slice + 1) * height) / slices) & cmask) -
     407             :                        slice_start;
     408             : 
     409         308 :         if (!slice_height)
     410           0 :             continue;
     411         308 :         bsrc = src + slice_start * stride;
     412             : 
     413             :         // first line - left neighbour prediction
     414         308 :         bsrc[0] += 0x80;
     415         308 :         c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
     416         308 :         bsrc += stride;
     417         308 :         if (slice_height <= 1)
     418           0 :             continue;
     419             :         // second line - first element has top prediction, the rest uses median
     420         308 :         C        = bsrc[-stride];
     421         308 :         bsrc[0] += C;
     422         308 :         A        = bsrc[0];
     423        4928 :         for (i = 1; i < FFMIN(width, 16); i++) { /* scalar loop (DSP need align 16) */
     424        4620 :             B        = bsrc[i - stride];
     425        4620 :             bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
     426        4620 :             C        = B;
     427        4620 :             A        = bsrc[i];
     428             :         }
     429         308 :         if (width > 16)
     430         924 :             c->llviddsp.add_median_pred(bsrc + 16, bsrc - stride + 16,
     431         616 :                                         bsrc + 16, width - 16, &A, &B);
     432             : 
     433         308 :         bsrc += stride;
     434             :         // the rest of lines use continuous median prediction
     435       33436 :         for (j = 2; j < slice_height; j++) {
     436       33128 :             c->llviddsp.add_median_pred(bsrc, bsrc - stride,
     437             :                                             bsrc, width, &A, &B);
     438       33128 :             bsrc += stride;
     439             :         }
     440             :     }
     441          77 : }
     442             : 
     443             : /* UtVideo interlaced mode treats every two lines as a single one,
     444             :  * so restoring function should take care of possible padding between
     445             :  * two parts of the same "line".
     446             :  */
     447          12 : static void restore_median_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
     448             :                                      int width, int height, int slices, int rmode)
     449             : {
     450             :     int i, j, slice;
     451             :     int A, B, C;
     452             :     uint8_t *bsrc;
     453             :     int slice_start, slice_height;
     454          12 :     const int cmask   = ~(rmode ? 3 : 1);
     455          12 :     const ptrdiff_t stride2 = stride << 1;
     456             : 
     457          60 :     for (slice = 0; slice < slices; slice++) {
     458          48 :         slice_start    = ((slice * height) / slices) & cmask;
     459          48 :         slice_height   = ((((slice + 1) * height) / slices) & cmask) -
     460             :                          slice_start;
     461          48 :         slice_height >>= 1;
     462          48 :         if (!slice_height)
     463           0 :             continue;
     464             : 
     465          48 :         bsrc = src + slice_start * stride;
     466             : 
     467             :         // first line - left neighbour prediction
     468          48 :         bsrc[0] += 0x80;
     469          48 :         A = c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
     470          48 :         c->llviddsp.add_left_pred(bsrc + stride, bsrc + stride, width, A);
     471          48 :         bsrc += stride2;
     472          48 :         if (slice_height <= 1)
     473           0 :             continue;
     474             :         // second line - first element has top prediction, the rest uses median
     475          48 :         C        = bsrc[-stride2];
     476          48 :         bsrc[0] += C;
     477          48 :         A        = bsrc[0];
     478         768 :         for (i = 1; i < FFMIN(width, 16); i++) { /* scalar loop (DSP need align 16) */
     479         720 :             B        = bsrc[i - stride2];
     480         720 :             bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
     481         720 :             C        = B;
     482         720 :             A        = bsrc[i];
     483             :         }
     484          48 :         if (width > 16)
     485         144 :             c->llviddsp.add_median_pred(bsrc + 16, bsrc - stride2 + 16,
     486          96 :                                         bsrc + 16, width - 16, &A, &B);
     487             : 
     488          96 :         c->llviddsp.add_median_pred(bsrc + stride, bsrc - stride,
     489          48 :                                         bsrc + stride, width, &A, &B);
     490          48 :         bsrc += stride2;
     491             :         // the rest of lines use continuous median prediction
     492         216 :         for (j = 2; j < slice_height; j++) {
     493         168 :             c->llviddsp.add_median_pred(bsrc, bsrc - stride2,
     494             :                                             bsrc, width, &A, &B);
     495         336 :             c->llviddsp.add_median_pred(bsrc + stride, bsrc - stride,
     496         168 :                                             bsrc + stride, width, &A, &B);
     497         168 :             bsrc += stride2;
     498             :         }
     499             :     }
     500          12 : }
     501             : 
     502          13 : static void restore_gradient_planar(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
     503             :                                     int width, int height, int slices, int rmode)
     504             : {
     505             :     int i, j, slice;
     506             :     int A, B, C;
     507             :     uint8_t *bsrc;
     508             :     int slice_start, slice_height;
     509          13 :     const int cmask = ~rmode;
     510          13 :     int min_width = FFMIN(width, 32);
     511             : 
     512          65 :     for (slice = 0; slice < slices; slice++) {
     513          52 :         slice_start  = ((slice * height) / slices) & cmask;
     514          52 :         slice_height = ((((slice + 1) * height) / slices) & cmask) -
     515             :                        slice_start;
     516             : 
     517          52 :         if (!slice_height)
     518           0 :             continue;
     519          52 :         bsrc = src + slice_start * stride;
     520             : 
     521             :         // first line - left neighbour prediction
     522          52 :         bsrc[0] += 0x80;
     523          52 :         c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
     524          52 :         bsrc += stride;
     525          52 :         if (slice_height <= 1)
     526           0 :             continue;
     527         502 :         for (j = 1; j < slice_height; j++) {
     528             :             // second line - first element has top prediction, the rest uses gradient
     529         450 :             bsrc[0] = (bsrc[0] + bsrc[-stride]) & 0xFF;
     530       14400 :             for (i = 1; i < min_width; i++) { /* dsp need align 32 */
     531       13950 :                 A = bsrc[i - stride];
     532       13950 :                 B = bsrc[i - (stride + 1)];
     533       13950 :                 C = bsrc[i - 1];
     534       13950 :                 bsrc[i] = (A - B + C + bsrc[i]) & 0xFF;
     535             :             }
     536         450 :             if (width > 32)
     537         322 :                 c->llviddsp.add_gradient_pred(bsrc + 32, stride, width - 32);
     538         450 :             bsrc += stride;
     539             :         }
     540             :     }
     541          13 : }
     542             : 
     543          12 : static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_t stride,
     544             :                                       int width, int height, int slices, int rmode)
     545             : {
     546             :     int i, j, slice;
     547             :     int A, B, C;
     548             :     uint8_t *bsrc;
     549             :     int slice_start, slice_height;
     550          12 :     const int cmask   = ~(rmode ? 3 : 1);
     551          12 :     const ptrdiff_t stride2 = stride << 1;
     552          12 :     int min_width = FFMIN(width, 32);
     553             : 
     554          60 :     for (slice = 0; slice < slices; slice++) {
     555          48 :         slice_start    = ((slice * height) / slices) & cmask;
     556          48 :         slice_height   = ((((slice + 1) * height) / slices) & cmask) -
     557             :                          slice_start;
     558          48 :         slice_height >>= 1;
     559          48 :         if (!slice_height)
     560           0 :             continue;
     561             : 
     562          48 :         bsrc = src + slice_start * stride;
     563             : 
     564             :         // first line - left neighbour prediction
     565          48 :         bsrc[0] += 0x80;
     566          48 :         A = c->llviddsp.add_left_pred(bsrc, bsrc, width, 0);
     567          48 :         c->llviddsp.add_left_pred(bsrc + stride, bsrc + stride, width, A);
     568          48 :         bsrc += stride2;
     569          48 :         if (slice_height <= 1)
     570           0 :             continue;
     571         264 :         for (j = 1; j < slice_height; j++) {
     572             :             // second line - first element has top prediction, the rest uses gradient
     573         216 :             bsrc[0] = (bsrc[0] + bsrc[-stride2]) & 0xFF;
     574        6912 :             for (i = 1; i < min_width; i++) { /* dsp need align 32 */
     575        6696 :                 A = bsrc[i - stride2];
     576        6696 :                 B = bsrc[i - (stride2 + 1)];
     577        6696 :                 C = bsrc[i - 1];
     578        6696 :                 bsrc[i] = (A - B + C + bsrc[i]) & 0xFF;
     579             :             }
     580         216 :             if (width > 32)
     581         160 :                 c->llviddsp.add_gradient_pred(bsrc + 32, stride2, width - 32);
     582             : 
     583         216 :             A = bsrc[-stride];
     584         216 :             B = bsrc[-(1 + stride + stride - width)];
     585         216 :             C = bsrc[width - 1];
     586         216 :             bsrc[stride] = (A - B + C + bsrc[stride]) & 0xFF;
     587       12032 :             for (i = 1; i < width; i++) {
     588       11816 :                 A = bsrc[i - stride];
     589       11816 :                 B = bsrc[i - (1 + stride)];
     590       11816 :                 C = bsrc[i - 1 + stride];
     591       11816 :                 bsrc[i + stride] = (A - B + C + bsrc[i + stride]) & 0xFF;
     592             :             }
     593         216 :             bsrc += stride2;
     594             :         }
     595             :     }
     596          12 : }
     597             : 
     598          57 : static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     599             :                         AVPacket *avpkt)
     600             : {
     601          57 :     const uint8_t *buf = avpkt->data;
     602          57 :     int buf_size = avpkt->size;
     603          57 :     UtvideoContext *c = avctx->priv_data;
     604             :     int i, j;
     605             :     const uint8_t *plane_start[5];
     606          57 :     int plane_size, max_slice_size = 0, slice_start, slice_end, slice_size;
     607             :     int ret;
     608             :     GetByteContext gb;
     609          57 :     ThreadFrame frame = { .f = data };
     610             : 
     611          57 :     if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
     612           0 :         return ret;
     613             : 
     614             :     /* parse plane structure to get frame flags and validate slice offsets */
     615          57 :     bytestream2_init(&gb, buf, buf_size);
     616             : 
     617          57 :     if (c->pack) {
     618             :         const uint8_t *packed_stream;
     619             :         const uint8_t *control_stream;
     620             :         GetByteContext pb;
     621             :         uint32_t nb_cbs;
     622             :         int left;
     623             : 
     624           0 :         c->frame_info = PRED_GRADIENT << 8;
     625             : 
     626           0 :         if (bytestream2_get_byte(&gb) != 1)
     627           0 :             return AVERROR_INVALIDDATA;
     628           0 :         bytestream2_skip(&gb, 3);
     629           0 :         c->offset = bytestream2_get_le32(&gb);
     630             : 
     631           0 :         if (buf_size <= c->offset + 8LL)
     632           0 :             return AVERROR_INVALIDDATA;
     633             : 
     634           0 :         bytestream2_init(&pb, buf + 8 + c->offset, buf_size - 8 - c->offset);
     635             : 
     636           0 :         nb_cbs = bytestream2_get_le32(&pb);
     637           0 :         if (nb_cbs > c->offset)
     638           0 :             return AVERROR_INVALIDDATA;
     639             : 
     640           0 :         packed_stream = buf + 8;
     641           0 :         control_stream = packed_stream + (c->offset - nb_cbs);
     642           0 :         left = control_stream - packed_stream;
     643             : 
     644           0 :         for (i = 0; i < c->planes; i++) {
     645           0 :             for (j = 0; j < c->slices; j++) {
     646           0 :                 c->packed_stream[i][j] = packed_stream;
     647           0 :                 c->packed_stream_size[i][j] = bytestream2_get_le32(&pb);
     648           0 :                 if (c->packed_stream_size[i][j] > left)
     649           0 :                     return AVERROR_INVALIDDATA;
     650           0 :                 left -= c->packed_stream_size[i][j];
     651           0 :                 packed_stream += c->packed_stream_size[i][j];
     652             :             }
     653             :         }
     654             : 
     655           0 :         left = buf + buf_size - control_stream;
     656             : 
     657           0 :         for (i = 0; i < c->planes; i++) {
     658           0 :             for (j = 0; j < c->slices; j++) {
     659           0 :                 c->control_stream[i][j] = control_stream;
     660           0 :                 c->control_stream_size[i][j] = bytestream2_get_le32(&pb);
     661           0 :                 if (c->control_stream_size[i][j] > left)
     662           0 :                     return AVERROR_INVALIDDATA;
     663           0 :                 left -= c->control_stream_size[i][j];
     664           0 :                 control_stream += c->control_stream_size[i][j];
     665             :             }
     666             :         }
     667          57 :     } else if (c->pro) {
     668           0 :         if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) {
     669           0 :             av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n");
     670           0 :             return AVERROR_INVALIDDATA;
     671             :         }
     672           0 :         c->frame_info = bytestream2_get_le32u(&gb);
     673           0 :         c->slices = ((c->frame_info >> 16) & 0xff) + 1;
     674           0 :         for (i = 0; i < c->planes; i++) {
     675           0 :             plane_start[i] = gb.buffer;
     676           0 :             if (bytestream2_get_bytes_left(&gb) < 1024 + 4 * c->slices) {
     677           0 :                 av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n");
     678           0 :                 return AVERROR_INVALIDDATA;
     679             :             }
     680           0 :             slice_start = 0;
     681           0 :             slice_end   = 0;
     682           0 :             for (j = 0; j < c->slices; j++) {
     683           0 :                 slice_end   = bytestream2_get_le32u(&gb);
     684           0 :                 if (slice_end < 0 || slice_end < slice_start ||
     685           0 :                     bytestream2_get_bytes_left(&gb) < slice_end + 1024LL) {
     686           0 :                     av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
     687           0 :                     return AVERROR_INVALIDDATA;
     688             :                 }
     689           0 :                 slice_size  = slice_end - slice_start;
     690           0 :                 slice_start = slice_end;
     691           0 :                 max_slice_size = FFMAX(max_slice_size, slice_size);
     692             :             }
     693           0 :             plane_size = slice_end;
     694           0 :             bytestream2_skipu(&gb, plane_size);
     695           0 :             bytestream2_skipu(&gb, 1024);
     696             :         }
     697           0 :         plane_start[c->planes] = gb.buffer;
     698             :     } else {
     699         240 :         for (i = 0; i < c->planes; i++) {
     700         183 :             plane_start[i] = gb.buffer;
     701         183 :             if (bytestream2_get_bytes_left(&gb) < 256 + 4 * c->slices) {
     702           0 :                 av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n");
     703           0 :                 return AVERROR_INVALIDDATA;
     704             :             }
     705         183 :             bytestream2_skipu(&gb, 256);
     706         183 :             slice_start = 0;
     707         183 :             slice_end   = 0;
     708         915 :             for (j = 0; j < c->slices; j++) {
     709         732 :                 slice_end   = bytestream2_get_le32u(&gb);
     710        1464 :                 if (slice_end < 0 || slice_end < slice_start ||
     711         732 :                     bytestream2_get_bytes_left(&gb) < slice_end) {
     712           0 :                     av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
     713           0 :                     return AVERROR_INVALIDDATA;
     714             :                 }
     715         732 :                 slice_size  = slice_end - slice_start;
     716         732 :                 slice_start = slice_end;
     717         732 :                 max_slice_size = FFMAX(max_slice_size, slice_size);
     718             :             }
     719         183 :             plane_size = slice_end;
     720         183 :             bytestream2_skipu(&gb, plane_size);
     721             :         }
     722          57 :         plane_start[c->planes] = gb.buffer;
     723          57 :         if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) {
     724           0 :             av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n");
     725           0 :             return AVERROR_INVALIDDATA;
     726             :         }
     727          57 :         c->frame_info = bytestream2_get_le32u(&gb);
     728             :     }
     729          57 :     av_log(avctx, AV_LOG_DEBUG, "frame information flags %"PRIX32"\n",
     730             :            c->frame_info);
     731             : 
     732          57 :     c->frame_pred = (c->frame_info >> 8) & 3;
     733             : 
     734          57 :     max_slice_size += 4*avctx->width;
     735             : 
     736          57 :     if (!c->pack) {
     737          57 :         av_fast_malloc(&c->slice_bits, &c->slice_bits_size,
     738          57 :                        max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE);
     739             : 
     740          57 :         if (!c->slice_bits) {
     741           0 :             av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n");
     742           0 :             return AVERROR(ENOMEM);
     743             :         }
     744             :     }
     745             : 
     746          57 :     switch (c->avctx->pix_fmt) {
     747          28 :     case AV_PIX_FMT_GBRP:
     748             :     case AV_PIX_FMT_GBRAP:
     749         124 :         for (i = 0; i < c->planes; i++) {
     750         192 :             ret = decode_plane(c, i, frame.f->data[i],
     751          96 :                                frame.f->linesize[i], avctx->width,
     752             :                                avctx->height, plane_start[i],
     753          96 :                                c->frame_pred == PRED_LEFT);
     754          96 :             if (ret)
     755           0 :                 return ret;
     756          96 :             if (c->frame_pred == PRED_MEDIAN) {
     757          53 :                 if (!c->interlaced) {
     758         100 :                     restore_median_planar(c, frame.f->data[i],
     759          50 :                                           frame.f->linesize[i], avctx->width,
     760             :                                           avctx->height, c->slices, 0);
     761             :                 } else {
     762           6 :                     restore_median_planar_il(c, frame.f->data[i],
     763           3 :                                              frame.f->linesize[i],
     764             :                                              avctx->width, avctx->height, c->slices,
     765             :                                              0);
     766             :                 }
     767          43 :             } else if (c->frame_pred == PRED_GRADIENT) {
     768           7 :                 if (!c->interlaced) {
     769           8 :                     restore_gradient_planar(c, frame.f->data[i],
     770           4 :                                             frame.f->linesize[i], avctx->width,
     771             :                                             avctx->height, c->slices, 0);
     772             :                 } else {
     773           6 :                     restore_gradient_planar_il(c, frame.f->data[i],
     774           3 :                                                frame.f->linesize[i],
     775             :                                                avctx->width, avctx->height, c->slices,
     776             :                                                0);
     777             :                 }
     778             :             }
     779             :         }
     780         112 :         c->utdsp.restore_rgb_planes(frame.f->data[2], frame.f->data[0], frame.f->data[1],
     781          84 :                                     frame.f->linesize[2], frame.f->linesize[0], frame.f->linesize[1],
     782             :                                     avctx->width, avctx->height);
     783          28 :         break;
     784           0 :     case AV_PIX_FMT_GBRAP10:
     785             :     case AV_PIX_FMT_GBRP10:
     786           0 :         for (i = 0; i < c->planes; i++) {
     787           0 :             ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i],
     788           0 :                                  frame.f->linesize[i] / 2, avctx->width,
     789             :                                  avctx->height, plane_start[i],
     790           0 :                                  plane_start[i + 1] - 1024,
     791           0 :                                  c->frame_pred == PRED_LEFT);
     792           0 :             if (ret)
     793           0 :                 return ret;
     794             :         }
     795           0 :         c->utdsp.restore_rgb_planes10((uint16_t *)frame.f->data[2], (uint16_t *)frame.f->data[0], (uint16_t *)frame.f->data[1],
     796           0 :                                       frame.f->linesize[2] / 2, frame.f->linesize[0] / 2, frame.f->linesize[1] / 2,
     797             :                                       avctx->width, avctx->height);
     798           0 :         break;
     799          14 :     case AV_PIX_FMT_YUV420P:
     800          56 :         for (i = 0; i < 3; i++) {
     801         126 :             ret = decode_plane(c, i, frame.f->data[i], frame.f->linesize[i],
     802          84 :                                avctx->width >> !!i, avctx->height >> !!i,
     803          42 :                                plane_start[i], c->frame_pred == PRED_LEFT);
     804          42 :             if (ret)
     805           0 :                 return ret;
     806          42 :             if (c->frame_pred == PRED_MEDIAN) {
     807          15 :                 if (!c->interlaced) {
     808          36 :                     restore_median_planar(c, frame.f->data[i], frame.f->linesize[i],
     809          24 :                                           avctx->width >> !!i, avctx->height >> !!i,
     810             :                                           c->slices, !i);
     811             :                 } else {
     812           9 :                     restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i],
     813           3 :                                              avctx->width  >> !!i,
     814           3 :                                              avctx->height >> !!i,
     815             :                                              c->slices, !i);
     816             :                 }
     817          27 :             } else if (c->frame_pred == PRED_GRADIENT) {
     818           6 :                 if (!c->interlaced) {
     819           9 :                     restore_gradient_planar(c, frame.f->data[i], frame.f->linesize[i],
     820           6 :                                             avctx->width >> !!i, avctx->height >> !!i,
     821             :                                             c->slices, !i);
     822             :                 } else {
     823           9 :                     restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i],
     824           3 :                                                avctx->width  >> !!i,
     825           3 :                                                avctx->height >> !!i,
     826             :                                                c->slices, !i);
     827             :                 }
     828             :             }
     829             :         }
     830          14 :         break;
     831          11 :     case AV_PIX_FMT_YUV422P:
     832          44 :         for (i = 0; i < 3; i++) {
     833          66 :             ret = decode_plane(c, i, frame.f->data[i], frame.f->linesize[i],
     834          33 :                                avctx->width >> !!i, avctx->height,
     835          33 :                                plane_start[i], c->frame_pred == PRED_LEFT);
     836          33 :             if (ret)
     837           0 :                 return ret;
     838          33 :             if (c->frame_pred == PRED_MEDIAN) {
     839          15 :                 if (!c->interlaced) {
     840          24 :                     restore_median_planar(c, frame.f->data[i], frame.f->linesize[i],
     841          12 :                                           avctx->width >> !!i, avctx->height,
     842             :                                           c->slices, 0);
     843             :                 } else {
     844           6 :                     restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i],
     845           3 :                                              avctx->width >> !!i, avctx->height,
     846             :                                              c->slices, 0);
     847             :                 }
     848          18 :             } else if (c->frame_pred == PRED_GRADIENT) {
     849           6 :                 if (!c->interlaced) {
     850           6 :                     restore_gradient_planar(c, frame.f->data[i], frame.f->linesize[i],
     851           3 :                                             avctx->width >> !!i, avctx->height,
     852             :                                             c->slices, 0);
     853             :                 } else {
     854           6 :                     restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i],
     855           3 :                                                avctx->width  >> !!i, avctx->height,
     856             :                                                c->slices, 0);
     857             :                 }
     858             :             }
     859             :         }
     860          11 :         break;
     861           4 :     case AV_PIX_FMT_YUV444P:
     862          16 :         for (i = 0; i < 3; i++) {
     863          12 :             ret = decode_plane(c, i, frame.f->data[i], frame.f->linesize[i],
     864             :                                avctx->width, avctx->height,
     865          12 :                                plane_start[i], c->frame_pred == PRED_LEFT);
     866          12 :             if (ret)
     867           0 :                 return ret;
     868          12 :             if (c->frame_pred == PRED_MEDIAN) {
     869           6 :                 if (!c->interlaced) {
     870           3 :                     restore_median_planar(c, frame.f->data[i], frame.f->linesize[i],
     871             :                                           avctx->width, avctx->height,
     872             :                                           c->slices, 0);
     873             :                 } else {
     874           3 :                     restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i],
     875             :                                              avctx->width, avctx->height,
     876             :                                              c->slices, 0);
     877             :                 }
     878           6 :             } else if (c->frame_pred == PRED_GRADIENT) {
     879           6 :                 if (!c->interlaced) {
     880           3 :                     restore_gradient_planar(c, frame.f->data[i], frame.f->linesize[i],
     881             :                                             avctx->width, avctx->height,
     882             :                                             c->slices, 0);
     883             :                 } else {
     884           3 :                     restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i],
     885             :                                                avctx->width, avctx->height,
     886             :                                                c->slices, 0);
     887             :                 }
     888             :             }
     889             :         }
     890           4 :         break;
     891           0 :     case AV_PIX_FMT_YUV422P10:
     892           0 :         for (i = 0; i < 3; i++) {
     893           0 :             ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], frame.f->linesize[i] / 2,
     894           0 :                                  avctx->width >> !!i, avctx->height,
     895           0 :                                  plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT);
     896           0 :             if (ret)
     897           0 :                 return ret;
     898             :         }
     899           0 :         break;
     900             :     }
     901             : 
     902          57 :     frame.f->key_frame = 1;
     903          57 :     frame.f->pict_type = AV_PICTURE_TYPE_I;
     904          57 :     frame.f->interlaced_frame = !!c->interlaced;
     905             : 
     906          57 :     *got_frame = 1;
     907             : 
     908             :     /* always report that the buffer was completely consumed */
     909          57 :     return buf_size;
     910             : }
     911             : 
     912          46 : static av_cold int decode_init(AVCodecContext *avctx)
     913             : {
     914          46 :     UtvideoContext * const c = avctx->priv_data;
     915             : 
     916          46 :     c->avctx = avctx;
     917             : 
     918          46 :     ff_utvideodsp_init(&c->utdsp);
     919          46 :     ff_bswapdsp_init(&c->bdsp);
     920          46 :     ff_llviddsp_init(&c->llviddsp);
     921             : 
     922          46 :     c->slice_bits_size = 0;
     923             : 
     924          46 :     switch (avctx->codec_tag) {
     925          10 :     case MKTAG('U', 'L', 'R', 'G'):
     926          10 :         c->planes      = 3;
     927          10 :         avctx->pix_fmt = AV_PIX_FMT_GBRP;
     928          10 :         break;
     929           8 :     case MKTAG('U', 'L', 'R', 'A'):
     930           8 :         c->planes      = 4;
     931           8 :         avctx->pix_fmt = AV_PIX_FMT_GBRAP;
     932           8 :         break;
     933           4 :     case MKTAG('U', 'L', 'Y', '0'):
     934           4 :         c->planes      = 3;
     935           4 :         avctx->pix_fmt = AV_PIX_FMT_YUV420P;
     936           4 :         avctx->colorspace = AVCOL_SPC_BT470BG;
     937           4 :         break;
     938           4 :     case MKTAG('U', 'L', 'Y', '2'):
     939           4 :         c->planes      = 3;
     940           4 :         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
     941           4 :         avctx->colorspace = AVCOL_SPC_BT470BG;
     942           4 :         break;
     943           0 :     case MKTAG('U', 'L', 'Y', '4'):
     944           0 :         c->planes      = 3;
     945           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
     946           0 :         avctx->colorspace = AVCOL_SPC_BT470BG;
     947           0 :         break;
     948           0 :     case MKTAG('U', 'Q', 'Y', '2'):
     949           0 :         c->planes      = 3;
     950           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
     951           0 :         break;
     952           0 :     case MKTAG('U', 'Q', 'R', 'G'):
     953           0 :         c->planes      = 3;
     954           0 :         avctx->pix_fmt = AV_PIX_FMT_GBRP10;
     955           0 :         break;
     956           0 :     case MKTAG('U', 'Q', 'R', 'A'):
     957           0 :         c->planes      = 4;
     958           0 :         avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
     959           0 :         break;
     960           6 :     case MKTAG('U', 'L', 'H', '0'):
     961           6 :         c->planes      = 3;
     962           6 :         avctx->pix_fmt = AV_PIX_FMT_YUV420P;
     963           6 :         avctx->colorspace = AVCOL_SPC_BT709;
     964           6 :         break;
     965           6 :     case MKTAG('U', 'L', 'H', '2'):
     966           6 :         c->planes      = 3;
     967           6 :         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
     968           6 :         avctx->colorspace = AVCOL_SPC_BT709;
     969           6 :         break;
     970           8 :     case MKTAG('U', 'L', 'H', '4'):
     971           8 :         c->planes      = 3;
     972           8 :         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
     973           8 :         avctx->colorspace = AVCOL_SPC_BT709;
     974           8 :         break;
     975           0 :     case MKTAG('U', 'M', 'Y', '2'):
     976           0 :         c->planes      = 3;
     977           0 :         c->pack        = 1;
     978           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
     979           0 :         avctx->colorspace = AVCOL_SPC_BT470BG;
     980           0 :         break;
     981           0 :     case MKTAG('U', 'M', 'H', '2'):
     982           0 :         c->planes      = 3;
     983           0 :         c->pack        = 1;
     984           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
     985           0 :         avctx->colorspace = AVCOL_SPC_BT709;
     986           0 :         break;
     987           0 :     case MKTAG('U', 'M', 'Y', '4'):
     988           0 :         c->planes      = 3;
     989           0 :         c->pack        = 1;
     990           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
     991           0 :         avctx->colorspace = AVCOL_SPC_BT470BG;
     992           0 :         break;
     993           0 :     case MKTAG('U', 'M', 'H', '4'):
     994           0 :         c->planes      = 3;
     995           0 :         c->pack        = 1;
     996           0 :         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
     997           0 :         avctx->colorspace = AVCOL_SPC_BT709;
     998           0 :         break;
     999           0 :     case MKTAG('U', 'M', 'R', 'G'):
    1000           0 :         c->planes      = 3;
    1001           0 :         c->pack        = 1;
    1002           0 :         avctx->pix_fmt = AV_PIX_FMT_GBRP;
    1003           0 :         break;
    1004           0 :     case MKTAG('U', 'M', 'R', 'A'):
    1005           0 :         c->planes      = 4;
    1006           0 :         c->pack        = 1;
    1007           0 :         avctx->pix_fmt = AV_PIX_FMT_GBRAP;
    1008           0 :         break;
    1009           0 :     default:
    1010           0 :         av_log(avctx, AV_LOG_ERROR, "Unknown Ut Video FOURCC provided (%08X)\n",
    1011             :                avctx->codec_tag);
    1012           0 :         return AVERROR_INVALIDDATA;
    1013             :     }
    1014             : 
    1015          46 :     if (c->pack && avctx->extradata_size >= 16) {
    1016           0 :         av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
    1017           0 :                avctx->extradata[3], avctx->extradata[2],
    1018           0 :                avctx->extradata[1], avctx->extradata[0]);
    1019           0 :         av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
    1020           0 :                AV_RB32(avctx->extradata + 4));
    1021           0 :         c->compression = avctx->extradata[8];
    1022           0 :         if (c->compression != 2)
    1023           0 :             avpriv_request_sample(avctx, "Unknown compression type");
    1024           0 :         c->slices      = avctx->extradata[9] + 1;
    1025          46 :     } else if (avctx->extradata_size >= 16) {
    1026         184 :         av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
    1027          92 :                avctx->extradata[3], avctx->extradata[2],
    1028          92 :                avctx->extradata[1], avctx->extradata[0]);
    1029          46 :         av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
    1030          46 :                AV_RB32(avctx->extradata + 4));
    1031          46 :         c->frame_info_size = AV_RL32(avctx->extradata + 8);
    1032          46 :         c->flags           = AV_RL32(avctx->extradata + 12);
    1033             : 
    1034          46 :         if (c->frame_info_size != 4)
    1035           0 :             avpriv_request_sample(avctx, "Frame info not 4 bytes");
    1036          46 :         av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags);
    1037          46 :         c->slices      = (c->flags >> 24) + 1;
    1038          46 :         c->compression = c->flags & 1;
    1039          46 :         c->interlaced  = c->flags & 0x800;
    1040           0 :     } else if (avctx->extradata_size == 8) {
    1041           0 :         av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
    1042           0 :                avctx->extradata[3], avctx->extradata[2],
    1043           0 :                avctx->extradata[1], avctx->extradata[0]);
    1044           0 :         av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
    1045           0 :                AV_RB32(avctx->extradata + 4));
    1046           0 :         c->interlaced  = 0;
    1047           0 :         c->pro         = 1;
    1048           0 :         c->frame_info_size = 4;
    1049             :     } else {
    1050           0 :         av_log(avctx, AV_LOG_ERROR,
    1051             :                "Insufficient extradata size %d, should be at least 16\n",
    1052             :                avctx->extradata_size);
    1053           0 :         return AVERROR_INVALIDDATA;
    1054             :     }
    1055             : 
    1056          46 :     return 0;
    1057             : }
    1058             : 
    1059          46 : static av_cold int decode_end(AVCodecContext *avctx)
    1060             : {
    1061          46 :     UtvideoContext * const c = avctx->priv_data;
    1062             : 
    1063          46 :     av_freep(&c->slice_bits);
    1064             : 
    1065          46 :     return 0;
    1066             : }
    1067             : 
    1068             : AVCodec ff_utvideo_decoder = {
    1069             :     .name           = "utvideo",
    1070             :     .long_name      = NULL_IF_CONFIG_SMALL("Ut Video"),
    1071             :     .type           = AVMEDIA_TYPE_VIDEO,
    1072             :     .id             = AV_CODEC_ID_UTVIDEO,
    1073             :     .priv_data_size = sizeof(UtvideoContext),
    1074             :     .init           = decode_init,
    1075             :     .close          = decode_end,
    1076             :     .decode         = decode_frame,
    1077             :     .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
    1078             :     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
    1079             : };

Generated by: LCOV version 1.13