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

Generated by: LCOV version 1.13