LCOV - code coverage report
Current view: top level - libavcodec - xfaceenc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 105 109 96.3 %
Date: 2017-12-15 11:05:35 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1990 James Ashton - Sydney University
       3             :  * Copyright (c) 2012 Stefano Sabatini
       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             :  * X-Face encoder, based on libcompface, by James Ashton.
      25             :  */
      26             : 
      27             : #include "xface.h"
      28             : #include "avcodec.h"
      29             : #include "internal.h"
      30             : #include "libavutil/avassert.h"
      31             : 
      32             : typedef struct XFaceContext {
      33             :     AVClass *class;
      34             :     uint8_t bitmap[XFACE_PIXELS]; ///< image used internally for decoding
      35             :     int max_line_len;             ///< max line length for compressed data
      36             :     int set_header;               ///< set X-Face header in the output
      37             : } XFaceContext;
      38             : 
      39       75946 : static int all_same(char *bitmap, int w, int h)
      40             : {
      41             :     char val, *row;
      42             :     int x;
      43             : 
      44       75946 :     val = *bitmap;
      45      226959 :     while (h--) {
      46      124163 :         row = bitmap;
      47      124163 :         x = w;
      48      483880 :         while (x--)
      49      284650 :             if (*(row++) != val)
      50       49096 :                 return 0;
      51       75067 :         bitmap += XFACE_WIDTH;
      52             :     }
      53       26850 :     return 1;
      54             : }
      55             : 
      56      222970 : static int all_black(char *bitmap, int w, int h)
      57             : {
      58      222970 :     if (w > 3) {
      59       53583 :         w /= 2;
      60       53583 :         h /= 2;
      61      119619 :         return (all_black(bitmap, w, h) && all_black(bitmap + w, w, h) &&
      62      107186 :                 all_black(bitmap + XFACE_WIDTH * h, w, h) &&
      63       23589 :                 all_black(bitmap + XFACE_WIDTH * h + w, w, h));
      64             :     } else {
      65             :         /* at least one pixel in the 2x2 grid is non-zero */
      66      335368 :         return *bitmap || *(bitmap + 1) ||
      67      268469 :                *(bitmap + XFACE_WIDTH) || *(bitmap + XFACE_WIDTH + 1);
      68             :     }
      69             : }
      70             : 
      71      106612 : static int all_white(char *bitmap, int w, int h)
      72             : {
      73      106612 :     return *bitmap == 0 && all_same(bitmap, w, h);
      74             : }
      75             : 
      76             : typedef struct {
      77             :     ProbRange prob_ranges[XFACE_PIXELS*2];
      78             :     int prob_ranges_idx;
      79             : } ProbRangesQueue;
      80             : 
      81      193204 : static inline int pq_push(ProbRangesQueue *pq, const ProbRange *p)
      82             : {
      83      193204 :     if (pq->prob_ranges_idx >= XFACE_PIXELS * 2 - 1)
      84           0 :         return -1;
      85      193204 :     pq->prob_ranges[pq->prob_ranges_idx++] = *p;
      86      193204 :     return 0;
      87             : }
      88             : 
      89       97603 : static void push_greys(ProbRangesQueue *pq, char *bitmap, int w, int h)
      90             : {
      91       97603 :     if (w > 3) {
      92       11011 :         w /= 2;
      93       11011 :         h /= 2;
      94       11011 :         push_greys(pq, bitmap,                       w, h);
      95       11011 :         push_greys(pq, bitmap + w,                   w, h);
      96       11011 :         push_greys(pq, bitmap + XFACE_WIDTH * h,     w, h);
      97       11011 :         push_greys(pq, bitmap + XFACE_WIDTH * h + w, w, h);
      98             :     } else {
      99       86592 :         const ProbRange *p = ff_xface_probranges_2x2 +
     100       86592 :                  *bitmap +
     101       86592 :             2 * *(bitmap + 1) +
     102      259776 :             4 * *(bitmap + XFACE_WIDTH) +
     103       86592 :             8 * *(bitmap + XFACE_WIDTH + 1);
     104       86592 :         pq_push(pq, p);
     105             :     }
     106       97603 : }
     107             : 
     108      106612 : static void encode_block(char *bitmap, int w, int h, int level, ProbRangesQueue *pq)
     109             : {
     110      106612 :     if (all_white(bitmap, w, h)) {
     111       26850 :         pq_push(pq, &ff_xface_probranges_per_level[level][XFACE_COLOR_WHITE]);
     112       79762 :     } else if (all_black(bitmap, w, h)) {
     113       53559 :         pq_push(pq, &ff_xface_probranges_per_level[level][XFACE_COLOR_BLACK]);
     114       53559 :         push_greys(pq, bitmap, w, h);
     115             :     } else {
     116       26203 :         pq_push(pq, &ff_xface_probranges_per_level[level][XFACE_COLOR_GREY]);
     117       26203 :         w /= 2;
     118       26203 :         h /= 2;
     119       26203 :         level++;
     120       26203 :         encode_block(bitmap,                       w, h, level, pq);
     121       26203 :         encode_block(bitmap + w,                   w, h, level, pq);
     122       26203 :         encode_block(bitmap + h * XFACE_WIDTH,     w, h, level, pq);
     123       26203 :         encode_block(bitmap + w + h * XFACE_WIDTH, w, h, level, pq);
     124             :     }
     125      106612 : }
     126             : 
     127      193204 : static void push_integer(BigInt *b, const ProbRange *prange)
     128             : {
     129             :     uint8_t r;
     130             : 
     131      193204 :     ff_big_div(b, prange->range, &r);
     132      193204 :     ff_big_mul(b, 0);
     133      193204 :     ff_big_add(b, r + prange->offset);
     134      193204 : }
     135             : 
     136         200 : static int xface_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     137             :                               const AVFrame *frame, int *got_packet)
     138             : {
     139         200 :     XFaceContext *xface = avctx->priv_data;
     140         200 :     ProbRangesQueue pq = {{{ 0 }}, 0};
     141             :     uint8_t bitmap_copy[XFACE_PIXELS];
     142         200 :     BigInt b = {0};
     143         200 :     int i, j, k, ret = 0;
     144             :     const uint8_t *buf;
     145             :     uint8_t *p;
     146             :     char intbuf[XFACE_MAX_DIGITS];
     147             : 
     148         200 :     if (avctx->width || avctx->height) {
     149         200 :         if (avctx->width != XFACE_WIDTH || avctx->height != XFACE_HEIGHT) {
     150           0 :             av_log(avctx, AV_LOG_ERROR,
     151             :                    "Size value %dx%d not supported, only accepts a size of %dx%d\n",
     152             :                    avctx->width, avctx->height, XFACE_WIDTH, XFACE_HEIGHT);
     153           0 :             return AVERROR(EINVAL);
     154             :         }
     155             :     }
     156         200 :     avctx->width  = XFACE_WIDTH;
     157         200 :     avctx->height = XFACE_HEIGHT;
     158             : 
     159             :     /* convert image from MONOWHITE to 1=black 0=white bitmap */
     160         200 :     buf = frame->data[0];
     161         200 :     i = j = 0;
     162             :     do {
     163      518400 :         for (k = 0; k < 8; k++)
     164      460800 :             xface->bitmap[i++] = (buf[j]>>(7-k))&1;
     165       57600 :         if (++j == XFACE_WIDTH/8) {
     166        9600 :             buf += frame->linesize[0];
     167        9600 :             j = 0;
     168             :         }
     169       57600 :     } while (i < XFACE_PIXELS);
     170             : 
     171             :     /* create a copy of bitmap */
     172         200 :     memcpy(bitmap_copy, xface->bitmap, XFACE_PIXELS);
     173         200 :     ff_xface_generate_face(xface->bitmap, bitmap_copy);
     174             : 
     175         200 :     encode_block(xface->bitmap,                         16, 16, 0, &pq);
     176         200 :     encode_block(xface->bitmap + 16,                    16, 16, 0, &pq);
     177         200 :     encode_block(xface->bitmap + 32,                    16, 16, 0, &pq);
     178         200 :     encode_block(xface->bitmap + XFACE_WIDTH * 16,      16, 16, 0, &pq);
     179         200 :     encode_block(xface->bitmap + XFACE_WIDTH * 16 + 16, 16, 16, 0, &pq);
     180         200 :     encode_block(xface->bitmap + XFACE_WIDTH * 16 + 32, 16, 16, 0, &pq);
     181         200 :     encode_block(xface->bitmap + XFACE_WIDTH * 32,      16, 16, 0, &pq);
     182         200 :     encode_block(xface->bitmap + XFACE_WIDTH * 32 + 16, 16, 16, 0, &pq);
     183         200 :     encode_block(xface->bitmap + XFACE_WIDTH * 32 + 32, 16, 16, 0, &pq);
     184             : 
     185      193604 :     while (pq.prob_ranges_idx > 0)
     186      193204 :         push_integer(&b, &pq.prob_ranges[--pq.prob_ranges_idx]);
     187             : 
     188             :     /* write the inverted big integer in b to intbuf */
     189         200 :     i = 0;
     190         200 :     av_assert0(b.nb_words < XFACE_MAX_WORDS);
     191       67910 :     while (b.nb_words) {
     192             :         uint8_t r;
     193       67510 :         ff_big_div(&b, XFACE_PRINTS, &r);
     194       67510 :         av_assert0(i < sizeof(intbuf));
     195       67510 :         intbuf[i++] = r + XFACE_FIRST_PRINT;
     196             :     }
     197             : 
     198         200 :     if ((ret = ff_alloc_packet2(avctx, pkt, i+2, 0)) < 0)
     199           0 :         return ret;
     200             : 
     201             :     /* revert the number, and close the buffer */
     202         200 :     p = pkt->data;
     203       67910 :     while (--i >= 0)
     204       67510 :         *(p++) = intbuf[i];
     205         200 :     *(p++) = '\n';
     206         200 :     *(p++) = 0;
     207             : 
     208         200 :     pkt->flags |= AV_PKT_FLAG_KEY;
     209         200 :     *got_packet = 1;
     210             : 
     211         200 :     return 0;
     212             : }
     213             : 
     214             : AVCodec ff_xface_encoder = {
     215             :     .name           = "xface",
     216             :     .long_name      = NULL_IF_CONFIG_SMALL("X-face image"),
     217             :     .type           = AVMEDIA_TYPE_VIDEO,
     218             :     .id             = AV_CODEC_ID_XFACE,
     219             :     .priv_data_size = sizeof(XFaceContext),
     220             :     .encode2        = xface_encode_frame,
     221             :     .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE },
     222             :     .capabilities   = AV_CODEC_CAP_INTRA_ONLY,
     223             : };

Generated by: LCOV version 1.13