LCOV - code coverage report
Current view: top level - libavcodec - roqvideodec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 133 143 93.0 %
Date: 2017-12-17 04:34:43 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2003 The FFmpeg project
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Lesser General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2.1 of the License, or (at your option) any later version.
      10             :  *
      11             :  * FFmpeg is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with FFmpeg; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : /**
      22             :  * @file
      23             :  * id RoQ Video Decoder by Dr. Tim Ferguson
      24             :  * For more information about the id RoQ format, visit:
      25             :  *   http://www.csse.monash.edu.au/~timf/
      26             :  */
      27             : 
      28             : #include "libavutil/avassert.h"
      29             : #include "libavutil/imgutils.h"
      30             : 
      31             : #include "avcodec.h"
      32             : #include "bytestream.h"
      33             : #include "internal.h"
      34             : #include "roqvideo.h"
      35             : 
      36         225 : static void roqvideo_decode_frame(RoqContext *ri)
      37             : {
      38         225 :     unsigned int chunk_id = 0, chunk_arg = 0;
      39         225 :     unsigned long chunk_size = 0;
      40         225 :     int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
      41             :     int vqid, xpos, ypos, xp, yp, x, y, mx, my;
      42         225 :     int frame_stats[2][4] = {{0},{0}};
      43             :     roq_qcell *qcell;
      44             :     int64_t chunk_start;
      45             : 
      46         653 :     while (bytestream2_get_bytes_left(&ri->gb) >= 8) {
      47         428 :         chunk_id   = bytestream2_get_le16(&ri->gb);
      48         428 :         chunk_size = bytestream2_get_le32(&ri->gb);
      49         428 :         chunk_arg  = bytestream2_get_le16(&ri->gb);
      50             : 
      51         428 :         if(chunk_id == RoQ_QUAD_VQ)
      52         225 :             break;
      53         203 :         if(chunk_id == RoQ_QUAD_CODEBOOK) {
      54         203 :             if((nv1 = chunk_arg >> 8) == 0)
      55          67 :                 nv1 = 256;
      56         203 :             if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
      57           1 :                 nv2 = 256;
      58       51102 :             for(i = 0; i < nv1; i++) {
      59       50899 :                 ri->cb2x2[i].y[0] = bytestream2_get_byte(&ri->gb);
      60       50899 :                 ri->cb2x2[i].y[1] = bytestream2_get_byte(&ri->gb);
      61       50899 :                 ri->cb2x2[i].y[2] = bytestream2_get_byte(&ri->gb);
      62       50899 :                 ri->cb2x2[i].y[3] = bytestream2_get_byte(&ri->gb);
      63       50899 :                 ri->cb2x2[i].u    = bytestream2_get_byte(&ri->gb);
      64       50899 :                 ri->cb2x2[i].v    = bytestream2_get_byte(&ri->gb);
      65             :             }
      66       17934 :             for(i = 0; i < nv2; i++)
      67       88655 :                 for(j = 0; j < 4; j++)
      68       70924 :                     ri->cb4x4[i].idx[j] = bytestream2_get_byte(&ri->gb);
      69             :         }
      70             :     }
      71             : 
      72         225 :     chunk_start = bytestream2_tell(&ri->gb);
      73         225 :     xpos = ypos = 0;
      74             : 
      75         225 :     if (chunk_size > bytestream2_get_bytes_left(&ri->gb)) {
      76           0 :         av_log(ri->avctx, AV_LOG_ERROR, "Chunk does not fit in input buffer\n");
      77           0 :         chunk_size = bytestream2_get_bytes_left(&ri->gb);
      78             :     }
      79             : 
      80      113685 :     while (bytestream2_tell(&ri->gb) < chunk_start + chunk_size) {
      81      340342 :         for (yp = ypos; yp < ypos + 16; yp += 8)
      82      680707 :             for (xp = xpos; xp < xpos + 16; xp += 8) {
      83      453825 :                 if (bytestream2_tell(&ri->gb) >= chunk_start + chunk_size) {
      84           4 :                     av_log(ri->avctx, AV_LOG_VERBOSE, "Chunk is too short\n");
      85           4 :                     return;
      86             :                 }
      87      453821 :                 if (vqflg_pos < 0) {
      88       56771 :                     vqflg = bytestream2_get_le16(&ri->gb);
      89       56771 :                     vqflg_pos = 7;
      90             :                 }
      91      453821 :                 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
      92      453821 :                 frame_stats[0][vqid]++;
      93      453821 :                 vqflg_pos--;
      94             : 
      95      453821 :                 switch(vqid) {
      96      121738 :                 case RoQ_ID_MOT:
      97      121738 :                     break;
      98        9277 :                 case RoQ_ID_FCC: {
      99        9277 :                     int byte = bytestream2_get_byte(&ri->gb);
     100        9277 :                     mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
     101        9277 :                     my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
     102        9277 :                     ff_apply_motion_8x8(ri, xp, yp, mx, my);
     103        9277 :                     break;
     104             :                 }
     105        7001 :                 case RoQ_ID_SLD:
     106        7001 :                     qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb);
     107        7001 :                     ff_apply_vector_4x4(ri, xp,     yp,     ri->cb2x2 + qcell->idx[0]);
     108        7001 :                     ff_apply_vector_4x4(ri, xp + 4, yp,     ri->cb2x2 + qcell->idx[1]);
     109        7001 :                     ff_apply_vector_4x4(ri, xp,     yp + 4, ri->cb2x2 + qcell->idx[2]);
     110        7001 :                     ff_apply_vector_4x4(ri, xp + 4, yp + 4, ri->cb2x2 + qcell->idx[3]);
     111        7001 :                     break;
     112      315805 :                 case RoQ_ID_CCC:
     113     1578984 :                     for (k = 0; k < 4; k++) {
     114     1263209 :                         x = xp; y = yp;
     115     1263209 :                         if(k & 0x01) x += 4;
     116     1263209 :                         if(k & 0x02) y += 4;
     117             : 
     118     1263209 :                         if (bytestream2_tell(&ri->gb) >= chunk_start + chunk_size) {
     119          30 :                             av_log(ri->avctx, AV_LOG_VERBOSE, "Chunk is too short\n");
     120          30 :                             return;
     121             :                         }
     122     1263179 :                         if (vqflg_pos < 0) {
     123      157911 :                             vqflg = bytestream2_get_le16(&ri->gb);
     124      157911 :                             vqflg_pos = 7;
     125             :                         }
     126     1263179 :                         vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
     127     1263179 :                         frame_stats[1][vqid]++;
     128     1263179 :                         vqflg_pos--;
     129     1263179 :                         switch(vqid) {
     130      259115 :                         case RoQ_ID_MOT:
     131      259115 :                             break;
     132      521989 :                         case RoQ_ID_FCC: {
     133      521989 :                             int byte = bytestream2_get_byte(&ri->gb);
     134      521989 :                             mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
     135      521989 :                             my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
     136      521989 :                             ff_apply_motion_4x4(ri, x, y, mx, my);
     137      521989 :                             break;
     138             :                         }
     139      116817 :                         case RoQ_ID_SLD:
     140      116817 :                             qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb);
     141      116817 :                             ff_apply_vector_2x2(ri, x,     y,     ri->cb2x2 + qcell->idx[0]);
     142      116817 :                             ff_apply_vector_2x2(ri, x + 2, y,     ri->cb2x2 + qcell->idx[1]);
     143      116817 :                             ff_apply_vector_2x2(ri, x,     y + 2, ri->cb2x2 + qcell->idx[2]);
     144      116817 :                             ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + qcell->idx[3]);
     145      116817 :                             break;
     146      365258 :                         case RoQ_ID_CCC:
     147      365258 :                             ff_apply_vector_2x2(ri, x,     y,     ri->cb2x2 + bytestream2_get_byte(&ri->gb));
     148      365258 :                             ff_apply_vector_2x2(ri, x + 2, y,     ri->cb2x2 + bytestream2_get_byte(&ri->gb));
     149      365258 :                             ff_apply_vector_2x2(ri, x,     y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
     150      365258 :                             ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
     151      365258 :                             break;
     152             :                         }
     153             :                     }
     154      315775 :                     break;
     155      453791 :                 default:
     156             :                     av_assert2(0);
     157             :             }
     158             :         }
     159             : 
     160      113426 :         xpos += 16;
     161      113426 :         if (xpos >= ri->width) {
     162        3596 :             xpos -= ri->width;
     163        3596 :             ypos += 16;
     164             :         }
     165      113426 :         if(ypos >= ri->height)
     166         191 :             break;
     167             :     }
     168             : }
     169             : 
     170             : 
     171          10 : static av_cold int roq_decode_init(AVCodecContext *avctx)
     172             : {
     173          10 :     RoqContext *s = avctx->priv_data;
     174             : 
     175          10 :     s->avctx = avctx;
     176             : 
     177          10 :     if (avctx->width % 16 || avctx->height % 16) {
     178           0 :         avpriv_request_sample(avctx, "Dimensions not being a multiple of 16");
     179           0 :         return AVERROR_PATCHWELCOME;
     180             :     }
     181             : 
     182          10 :     s->width = avctx->width;
     183          10 :     s->height = avctx->height;
     184             : 
     185          10 :     s->last_frame    = av_frame_alloc();
     186          10 :     s->current_frame = av_frame_alloc();
     187          10 :     if (!s->current_frame || !s->last_frame) {
     188           0 :         av_frame_free(&s->current_frame);
     189           0 :         av_frame_free(&s->last_frame);
     190           0 :         return AVERROR(ENOMEM);
     191             :     }
     192             : 
     193          10 :     avctx->pix_fmt = AV_PIX_FMT_YUVJ444P;
     194          10 :     avctx->color_range = AVCOL_RANGE_JPEG;
     195             : 
     196          10 :     return 0;
     197             : }
     198             : 
     199         225 : static int roq_decode_frame(AVCodecContext *avctx,
     200             :                             void *data, int *got_frame,
     201             :                             AVPacket *avpkt)
     202             : {
     203         225 :     const uint8_t *buf = avpkt->data;
     204         225 :     int buf_size = avpkt->size;
     205         225 :     RoqContext *s = avctx->priv_data;
     206         225 :     int copy = !s->current_frame->data[0] && s->last_frame->data[0];
     207             :     int ret;
     208             : 
     209         225 :     if ((ret = ff_reget_buffer(avctx, s->current_frame)) < 0)
     210           0 :         return ret;
     211             : 
     212         225 :     if (copy) {
     213           4 :         ret = av_frame_copy(s->current_frame, s->last_frame);
     214           4 :         if (ret < 0)
     215           0 :             return ret;
     216             :     }
     217             : 
     218         225 :     bytestream2_init(&s->gb, buf, buf_size);
     219         225 :     roqvideo_decode_frame(s);
     220             : 
     221         225 :     if ((ret = av_frame_ref(data, s->current_frame)) < 0)
     222           0 :         return ret;
     223         225 :     *got_frame      = 1;
     224             : 
     225             :     /* shuffle frames */
     226         225 :     FFSWAP(AVFrame *, s->current_frame, s->last_frame);
     227             : 
     228         225 :     return buf_size;
     229             : }
     230             : 
     231          10 : static av_cold int roq_decode_end(AVCodecContext *avctx)
     232             : {
     233          10 :     RoqContext *s = avctx->priv_data;
     234             : 
     235          10 :     av_frame_free(&s->current_frame);
     236          10 :     av_frame_free(&s->last_frame);
     237             : 
     238          10 :     return 0;
     239             : }
     240             : 
     241             : AVCodec ff_roq_decoder = {
     242             :     .name           = "roqvideo",
     243             :     .long_name      = NULL_IF_CONFIG_SMALL("id RoQ video"),
     244             :     .type           = AVMEDIA_TYPE_VIDEO,
     245             :     .id             = AV_CODEC_ID_ROQ,
     246             :     .priv_data_size = sizeof(RoqContext),
     247             :     .init           = roq_decode_init,
     248             :     .close          = roq_decode_end,
     249             :     .decode         = roq_decode_frame,
     250             :     .capabilities   = AV_CODEC_CAP_DR1,
     251             : };

Generated by: LCOV version 1.13