LCOV - code coverage report
Current view: top level - libavcodec - ulti.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 200 255 78.4 %
Date: 2017-12-12 11:08:38 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * IBM Ultimotion Video Decoder
       3             :  * Copyright (C) 2004 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             :  * IBM Ultimotion Video Decoder.
      25             :  */
      26             : 
      27             : #include <stdio.h>
      28             : #include <stdlib.h>
      29             : #include <string.h>
      30             : 
      31             : #include "avcodec.h"
      32             : #include "bytestream.h"
      33             : #include "internal.h"
      34             : 
      35             : #include "ulti_cb.h"
      36             : 
      37             : typedef struct UltimotionDecodeContext {
      38             :     AVCodecContext *avctx;
      39             :     int width, height, blocks;
      40             :     AVFrame *frame;
      41             :     const uint8_t *ulti_codebook;
      42             :     GetByteContext gb;
      43             : } UltimotionDecodeContext;
      44             : 
      45           2 : static av_cold int ulti_decode_init(AVCodecContext *avctx)
      46             : {
      47           2 :     UltimotionDecodeContext *s = avctx->priv_data;
      48             : 
      49           2 :     s->avctx = avctx;
      50           2 :     s->width = avctx->width;
      51           2 :     s->height = avctx->height;
      52           2 :     s->blocks = (s->width / 8) * (s->height / 8);
      53           2 :     avctx->pix_fmt = AV_PIX_FMT_YUV410P;
      54           2 :     s->ulti_codebook = ulti_codebook;
      55             : 
      56           2 :     s->frame = av_frame_alloc();
      57           2 :     if (!s->frame)
      58           0 :         return AVERROR(ENOMEM);
      59             : 
      60           2 :     return 0;
      61             : }
      62             : 
      63           2 : static av_cold int ulti_decode_end(AVCodecContext *avctx){
      64           2 :     UltimotionDecodeContext *s = avctx->priv_data;
      65             : 
      66           2 :     av_frame_free(&s->frame);
      67             : 
      68           2 :     return 0;
      69             : }
      70             : 
      71             : static const int block_coords[8] = // 4x4 block coords in 8x8 superblock
      72             :     { 0, 0, 0, 4, 4, 4, 4, 0};
      73             : 
      74             : static const int angle_by_index[4] = { 0, 2, 6, 12};
      75             : 
      76             : /* Lookup tables for luma and chroma - used by ulti_convert_yuv() */
      77             : static const uint8_t ulti_lumas[64] =
      78             :     { 0x10, 0x13, 0x17, 0x1A, 0x1E, 0x21, 0x25, 0x28,
      79             :       0x2C, 0x2F, 0x33, 0x36, 0x3A, 0x3D, 0x41, 0x44,
      80             :       0x48, 0x4B, 0x4F, 0x52, 0x56, 0x59, 0x5C, 0x60,
      81             :       0x63, 0x67, 0x6A, 0x6E, 0x71, 0x75, 0x78, 0x7C,
      82             :       0x7F, 0x83, 0x86, 0x8A, 0x8D, 0x91, 0x94, 0x98,
      83             :       0x9B, 0x9F, 0xA2, 0xA5, 0xA9, 0xAC, 0xB0, 0xB3,
      84             :       0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8, 0xCC, 0xCF,
      85             :       0xD3, 0xD6, 0xDA, 0xDD, 0xE1, 0xE4, 0xE8, 0xEB};
      86             : 
      87             : static const uint8_t ulti_chromas[16] =
      88             :     { 0x60, 0x67, 0x6D, 0x73, 0x7A, 0x80, 0x86, 0x8D,
      89             :       0x93, 0x99, 0xA0, 0xA6, 0xAC, 0xB3, 0xB9, 0xC0};
      90             : 
      91             : /* convert Ultimotion YUV block (sixteen 6-bit Y samples and
      92             :  two 4-bit chroma samples) into standard YUV and put it into frame */
      93      206695 : static void ulti_convert_yuv(AVFrame *frame, int x, int y,
      94             :                              uint8_t *luma,int chroma)
      95             : {
      96             :     uint8_t *y_plane, *cr_plane, *cb_plane;
      97             :     int i;
      98             : 
      99      206695 :     y_plane = frame->data[0] + x + y * frame->linesize[0];
     100      206695 :     cr_plane = frame->data[1] + (x / 4) + (y / 4) * frame->linesize[1];
     101      206695 :     cb_plane = frame->data[2] + (x / 4) + (y / 4) * frame->linesize[2];
     102             : 
     103      206695 :     cr_plane[0] = ulti_chromas[chroma >> 4];
     104             : 
     105      206695 :     cb_plane[0] = ulti_chromas[chroma & 0xF];
     106             : 
     107             : 
     108     3513815 :     for(i = 0; i < 16; i++){
     109     3307120 :         y_plane[i & 3] = ulti_lumas[luma[i]];
     110     3307120 :         if((i & 3) == 3) { //next row
     111      826780 :             y_plane += frame->linesize[0];
     112             :         }
     113             :     }
     114      206695 : }
     115             : 
     116             : /* generate block like in MS Video1 */
     117       43140 : static void ulti_pattern(AVFrame *frame, int x, int y,
     118             :                          int f0, int f1, int Y0, int Y1, int chroma)
     119             : {
     120             :     uint8_t Luma[16];
     121             :     int mask, i;
     122      388260 :     for(mask = 0x80, i = 0; mask; mask >>= 1, i++) {
     123      345120 :         if(f0 & mask)
     124      146257 :             Luma[i] = Y1;
     125             :         else
     126      198863 :             Luma[i] = Y0;
     127             :     }
     128             : 
     129      388260 :     for(mask = 0x80, i = 8; mask; mask >>= 1, i++) {
     130      345120 :         if(f1 & mask)
     131      185919 :             Luma[i] = Y1;
     132             :         else
     133      159201 :             Luma[i] = Y0;
     134             :     }
     135             : 
     136       43140 :     ulti_convert_yuv(frame, x, y, Luma, chroma);
     137       43140 : }
     138             : 
     139             : /* fill block with some gradient */
     140      163555 : static void ulti_grad(AVFrame *frame, int x, int y, uint8_t *Y, int chroma, int angle)
     141             : {
     142             :     uint8_t Luma[16];
     143      163555 :     if(angle & 8) { //reverse order
     144             :         int t;
     145       56848 :         angle &= 0x7;
     146       56848 :         t = Y[0];
     147       56848 :         Y[0] = Y[3];
     148       56848 :         Y[3] = t;
     149       56848 :         t = Y[1];
     150       56848 :         Y[1] = Y[2];
     151       56848 :         Y[2] = t;
     152             :     }
     153      163555 :     switch(angle){
     154       44413 :     case 0:
     155       44413 :         Luma[0]  = Y[0]; Luma[1]  = Y[1]; Luma[2]  = Y[2]; Luma[3]  = Y[3];
     156       44413 :         Luma[4]  = Y[0]; Luma[5]  = Y[1]; Luma[6]  = Y[2]; Luma[7]  = Y[3];
     157       44413 :         Luma[8]  = Y[0]; Luma[9]  = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3];
     158       44413 :         Luma[12] = Y[0]; Luma[13] = Y[1]; Luma[14] = Y[2]; Luma[15] = Y[3];
     159       44413 :         break;
     160        4503 :     case 1:
     161        4503 :         Luma[0]  = Y[1]; Luma[1]  = Y[2]; Luma[2]  = Y[3]; Luma[3]  = Y[3];
     162        4503 :         Luma[4]  = Y[0]; Luma[5]  = Y[1]; Luma[6]  = Y[2]; Luma[7]  = Y[3];
     163        4503 :         Luma[8]  = Y[0]; Luma[9]  = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3];
     164        4503 :         Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2];
     165        4503 :         break;
     166        8134 :     case 2:
     167        8134 :         Luma[0]  = Y[1]; Luma[1]  = Y[2]; Luma[2]  = Y[3]; Luma[3]  = Y[3];
     168        8134 :         Luma[4]  = Y[1]; Luma[5]  = Y[2]; Luma[6]  = Y[2]; Luma[7]  = Y[3];
     169        8134 :         Luma[8]  = Y[0]; Luma[9]  = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2];
     170        8134 :         Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2];
     171        8134 :         break;
     172        8428 :     case 3:
     173        8428 :         Luma[0]  = Y[2]; Luma[1]  = Y[3]; Luma[2]  = Y[3]; Luma[3]  = Y[3];
     174        8428 :         Luma[4]  = Y[1]; Luma[5]  = Y[2]; Luma[6]  = Y[2]; Luma[7]  = Y[3];
     175        8428 :         Luma[8]  = Y[0]; Luma[9]  = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2];
     176        8428 :         Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[1];
     177        8428 :         break;
     178       75596 :     case 4:
     179       75596 :         Luma[0]  = Y[3]; Luma[1]  = Y[3]; Luma[2]  = Y[3]; Luma[3]  = Y[3];
     180       75596 :         Luma[4]  = Y[2]; Luma[5]  = Y[2]; Luma[6]  = Y[2]; Luma[7]  = Y[2];
     181       75596 :         Luma[8]  = Y[1]; Luma[9]  = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[1];
     182       75596 :         Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0];
     183       75596 :         break;
     184        7636 :     case 5:
     185        7636 :         Luma[0]  = Y[3]; Luma[1]  = Y[3]; Luma[2]  = Y[3]; Luma[3]  = Y[2];
     186        7636 :         Luma[4]  = Y[3]; Luma[5]  = Y[2]; Luma[6]  = Y[2]; Luma[7]  = Y[1];
     187        7636 :         Luma[8]  = Y[2]; Luma[9]  = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[0];
     188        7636 :         Luma[12] = Y[1]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0];
     189        7636 :         break;
     190       10624 :     case 6:
     191       10624 :         Luma[0]  = Y[3]; Luma[1]  = Y[3]; Luma[2]  = Y[2]; Luma[3]  = Y[2];
     192       10624 :         Luma[4]  = Y[3]; Luma[5]  = Y[2]; Luma[6]  = Y[1]; Luma[7]  = Y[1];
     193       10624 :         Luma[8]  = Y[2]; Luma[9]  = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0];
     194       10624 :         Luma[12] = Y[1]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0];
     195       10624 :         break;
     196        4221 :     case 7:
     197        4221 :         Luma[0]  = Y[3]; Luma[1]  = Y[3]; Luma[2]  = Y[2]; Luma[3]  = Y[1];
     198        4221 :         Luma[4]  = Y[3]; Luma[5]  = Y[2]; Luma[6]  = Y[1]; Luma[7]  = Y[0];
     199        4221 :         Luma[8]  = Y[3]; Luma[9]  = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0];
     200        4221 :         Luma[12] = Y[2]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0];
     201        4221 :         break;
     202           0 :     default:
     203           0 :         Luma[0]  = Y[0]; Luma[1]  = Y[0]; Luma[2]  = Y[1]; Luma[3]  = Y[1];
     204           0 :         Luma[4]  = Y[0]; Luma[5]  = Y[0]; Luma[6]  = Y[1]; Luma[7]  = Y[1];
     205           0 :         Luma[8]  = Y[2]; Luma[9]  = Y[2]; Luma[10] = Y[3]; Luma[11] = Y[3];
     206           0 :         Luma[12] = Y[2]; Luma[13] = Y[2]; Luma[14] = Y[3]; Luma[15] = Y[3];
     207           0 :         break;
     208             :     }
     209             : 
     210      163555 :     ulti_convert_yuv(frame, x, y, Luma, chroma);
     211      163555 : }
     212             : 
     213          62 : static int ulti_decode_frame(AVCodecContext *avctx,
     214             :                              void *data, int *got_frame,
     215             :                              AVPacket *avpkt)
     216             : {
     217          62 :     const uint8_t *buf = avpkt->data;
     218          62 :     int buf_size = avpkt->size;
     219          62 :     UltimotionDecodeContext *s=avctx->priv_data;
     220          62 :     int modifier = 0;
     221          62 :     int uniq = 0;
     222          62 :     int mode = 0;
     223          62 :     int blocks = 0;
     224          62 :     int done = 0;
     225          62 :     int x = 0, y = 0;
     226             :     int i, ret;
     227             :     int skip;
     228             :     int tmp;
     229             : 
     230          62 :     if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
     231           0 :         return ret;
     232             : 
     233          62 :     bytestream2_init(&s->gb, buf, buf_size);
     234             : 
     235          62 :     while(!done) {
     236             :         int idx;
     237       86713 :         if(blocks >= s->blocks || y >= s->height)
     238             :             break;//all blocks decoded
     239             : 
     240       86651 :         if (bytestream2_get_bytes_left(&s->gb) < 1)
     241           0 :             goto err;
     242       86651 :         idx = bytestream2_get_byteu(&s->gb);
     243       86651 :         if((idx & 0xF8) == 0x70) {
     244       17504 :             switch(idx) {
     245           0 :             case 0x70: //change modifier
     246           0 :                 modifier = bytestream2_get_byte(&s->gb);
     247           0 :                 if(modifier>1)
     248           0 :                     av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier);
     249           0 :                 break;
     250        4735 :             case 0x71: // set uniq flag
     251        4735 :                 uniq = 1;
     252        4735 :                 break;
     253       11510 :             case 0x72: //toggle mode
     254       11510 :                 mode = !mode;
     255       11510 :                 break;
     256           0 :             case 0x73: //end-of-frame
     257           0 :                 done = 1;
     258           0 :                 break;
     259        1259 :             case 0x74: //skip some blocks
     260        1259 :                 skip = bytestream2_get_byte(&s->gb);
     261        1259 :                 if ((blocks + skip) >= s->blocks)
     262           0 :                     break;
     263        1259 :                 blocks += skip;
     264        1259 :                 x += skip * 8;
     265        2875 :                 while(x >= s->width) {
     266         357 :                     x -= s->width;
     267         357 :                     y += 8;
     268             :                 }
     269        1259 :                 break;
     270           0 :             default:
     271           0 :                 av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx);
     272             :             }
     273             :         } else { //handle one block
     274             :             int code;
     275             :             int cf;
     276       69147 :             int angle = 0;
     277             :             uint8_t Y[4]; // luma samples of block
     278       69147 :             int tx = 0, ty = 0; //coords of subblock
     279       69147 :             int chroma = 0;
     280       69147 :             if (mode || uniq) {
     281       28189 :                 uniq = 0;
     282       28189 :                 cf = 1;
     283       28189 :                 chroma = 0;
     284             :             } else {
     285       40958 :                 cf = 0;
     286       40958 :                 if (idx) {
     287       39095 :                     chroma = bytestream2_get_byte(&s->gb);
     288             :                 }
     289             :             }
     290      345735 :             for (i = 0; i < 4; i++) { // for every subblock
     291      276588 :                 code = (idx >> (6 - i*2)) & 3; //extract 2 bits
     292      276588 :                 if(!code) //skip subblock
     293       69893 :                     continue;
     294      206695 :                 if(cf) {
     295       89307 :                     chroma = bytestream2_get_byte(&s->gb);
     296             :                 }
     297      206695 :                 tx = x + block_coords[i * 2];
     298      206695 :                 ty = y + block_coords[(i * 2) + 1];
     299      206695 :                 switch(code) {
     300       36515 :                 case 1:
     301       36515 :                     tmp = bytestream2_get_byte(&s->gb);
     302             : 
     303       36515 :                     angle = angle_by_index[(tmp >> 6) & 0x3];
     304             : 
     305       36515 :                     Y[0] = tmp & 0x3F;
     306       36515 :                     Y[1] = Y[0];
     307             : 
     308       36515 :                     if (angle) {
     309        9385 :                         Y[2] = Y[0]+1;
     310        9385 :                         if (Y[2] > 0x3F)
     311           0 :                             Y[2] = 0x3F;
     312        9385 :                         Y[3] = Y[2];
     313             :                     } else {
     314       27130 :                         Y[2] = Y[0];
     315       27130 :                         Y[3] = Y[0];
     316             :                     }
     317       36515 :                     break;
     318             : 
     319      110712 :                 case 2:
     320      110712 :                     if (modifier) { // unpack four luma samples
     321           0 :                         tmp = bytestream2_get_be24(&s->gb);
     322             : 
     323           0 :                         Y[0] = (tmp >> 18) & 0x3F;
     324           0 :                         Y[1] = (tmp >> 12) & 0x3F;
     325           0 :                         Y[2] = (tmp >> 6) & 0x3F;
     326           0 :                         Y[3] = tmp & 0x3F;
     327           0 :                         angle = 16;
     328             :                     } else { // retrieve luma samples from codebook
     329      110712 :                         tmp = bytestream2_get_be16(&s->gb);
     330             : 
     331      110712 :                         angle = (tmp >> 12) & 0xF;
     332      110712 :                         tmp &= 0xFFF;
     333      110712 :                         tmp <<= 2;
     334      110712 :                         Y[0] = s->ulti_codebook[tmp];
     335      110712 :                         Y[1] = s->ulti_codebook[tmp + 1];
     336      110712 :                         Y[2] = s->ulti_codebook[tmp + 2];
     337      110712 :                         Y[3] = s->ulti_codebook[tmp + 3];
     338             :                     }
     339      110712 :                     break;
     340             : 
     341       59468 :                 case 3:
     342       59468 :                     if (modifier) { // all 16 luma samples
     343             :                         uint8_t Luma[16];
     344             : 
     345           0 :                         if (bytestream2_get_bytes_left(&s->gb) < 12)
     346           0 :                             goto err;
     347           0 :                         tmp = bytestream2_get_be24u(&s->gb);
     348           0 :                         Luma[0] = (tmp >> 18) & 0x3F;
     349           0 :                         Luma[1] = (tmp >> 12) & 0x3F;
     350           0 :                         Luma[2] = (tmp >> 6) & 0x3F;
     351           0 :                         Luma[3] = tmp & 0x3F;
     352             : 
     353           0 :                         tmp = bytestream2_get_be24u(&s->gb);
     354           0 :                         Luma[4] = (tmp >> 18) & 0x3F;
     355           0 :                         Luma[5] = (tmp >> 12) & 0x3F;
     356           0 :                         Luma[6] = (tmp >> 6) & 0x3F;
     357           0 :                         Luma[7] = tmp & 0x3F;
     358             : 
     359           0 :                         tmp = bytestream2_get_be24u(&s->gb);
     360           0 :                         Luma[8] = (tmp >> 18) & 0x3F;
     361           0 :                         Luma[9] = (tmp >> 12) & 0x3F;
     362           0 :                         Luma[10] = (tmp >> 6) & 0x3F;
     363           0 :                         Luma[11] = tmp & 0x3F;
     364             : 
     365           0 :                         tmp = bytestream2_get_be24u(&s->gb);
     366           0 :                         Luma[12] = (tmp >> 18) & 0x3F;
     367           0 :                         Luma[13] = (tmp >> 12) & 0x3F;
     368           0 :                         Luma[14] = (tmp >> 6) & 0x3F;
     369           0 :                         Luma[15] = tmp & 0x3F;
     370             : 
     371           0 :                         ulti_convert_yuv(s->frame, tx, ty, Luma, chroma);
     372             :                     } else {
     373       59468 :                         if (bytestream2_get_bytes_left(&s->gb) < 4)
     374           0 :                             goto err;
     375       59468 :                         tmp = bytestream2_get_byteu(&s->gb);
     376       59468 :                         if(tmp & 0x80) {
     377       16328 :                             angle = (tmp >> 4) & 0x7;
     378       16328 :                             tmp = (tmp << 8) + bytestream2_get_byteu(&s->gb);
     379       16328 :                             Y[0] = (tmp >> 6) & 0x3F;
     380       16328 :                             Y[1] = tmp & 0x3F;
     381       16328 :                             Y[2] = bytestream2_get_byteu(&s->gb) & 0x3F;
     382       16328 :                             Y[3] = bytestream2_get_byteu(&s->gb) & 0x3F;
     383       16328 :                             ulti_grad(s->frame, tx, ty, Y, chroma, angle); //draw block
     384             :                         } else { // some patterns
     385       43140 :                             int f0 = tmp;
     386       43140 :                             int f1 = bytestream2_get_byteu(&s->gb);
     387       43140 :                             Y[0] = bytestream2_get_byteu(&s->gb) & 0x3F;
     388       43140 :                             Y[1] = bytestream2_get_byteu(&s->gb) & 0x3F;
     389       43140 :                             ulti_pattern(s->frame, tx, ty, f0, f1, Y[0], Y[1], chroma);
     390             :                         }
     391             :                     }
     392       59468 :                     break;
     393             :                 }
     394      206695 :                 if(code != 3)
     395      147227 :                     ulti_grad(s->frame, tx, ty, Y, chroma, angle); // draw block
     396             :             }
     397       69147 :             blocks++;
     398       69147 :                 x += 8;
     399       69147 :             if(x >= s->width) {
     400        1503 :                 x = 0;
     401        1503 :                 y += 8;
     402             :             }
     403             :         }
     404             :     }
     405             : 
     406          62 :     *got_frame = 1;
     407          62 :     if ((ret = av_frame_ref(data, s->frame)) < 0)
     408           0 :         return ret;
     409             : 
     410          62 :     return buf_size;
     411             : 
     412           0 : err:
     413           0 :     av_log(avctx, AV_LOG_ERROR,
     414             :            "Insufficient data\n");
     415           0 :     return AVERROR_INVALIDDATA;
     416             : }
     417             : 
     418             : AVCodec ff_ulti_decoder = {
     419             :     .name           = "ultimotion",
     420             :     .long_name      = NULL_IF_CONFIG_SMALL("IBM UltiMotion"),
     421             :     .type           = AVMEDIA_TYPE_VIDEO,
     422             :     .id             = AV_CODEC_ID_ULTI,
     423             :     .priv_data_size = sizeof(UltimotionDecodeContext),
     424             :     .init           = ulti_decode_init,
     425             :     .close          = ulti_decode_end,
     426             :     .decode         = ulti_decode_frame,
     427             :     .capabilities   = AV_CODEC_CAP_DR1,
     428             : };

Generated by: LCOV version 1.13