LCOV - code coverage report
Current view: top level - libavcodec - msvideo1enc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 148 152 97.4 %
Date: 2017-12-14 08:27:08 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Microsoft Video-1 Encoder
       3             :  * Copyright (c) 2009 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             :  * Microsoft Video-1 encoder
      25             :  */
      26             : 
      27             : #include "avcodec.h"
      28             : #include "internal.h"
      29             : #include "bytestream.h"
      30             : #include "libavutil/lfg.h"
      31             : #include "elbg.h"
      32             : #include "libavutil/imgutils.h"
      33             : /**
      34             :  * Encoder context
      35             :  */
      36             : typedef struct Msvideo1EncContext {
      37             :     AVCodecContext *avctx;
      38             :     AVLFG rnd;
      39             :     uint8_t *prev;
      40             : 
      41             :     int block[16*3];
      42             :     int block2[16*3];
      43             :     int codebook[8*3];
      44             :     int codebook2[8*3];
      45             :     int output[16*3];
      46             :     int output2[16*3];
      47             :     int avg[3];
      48             :     int bestpos;
      49             :     int keyint;
      50             : } Msvideo1EncContext;
      51             : 
      52             : enum MSV1Mode{
      53             :     MODE_SKIP = 0,
      54             :     MODE_FILL,
      55             :     MODE_2COL,
      56             :     MODE_8COL,
      57             : };
      58             : 
      59             : #define SKIP_PREFIX 0x8400
      60             : #define SKIPS_MAX 0x03FF
      61             : #define MKRGB555(in, off) (((in)[off] << 10) | ((in)[(off) + 1] << 5) | ((in)[(off) + 2]))
      62             : 
      63             : static const int remap[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 };
      64             : 
      65         150 : static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
      66             :                                const AVFrame *pict, int *got_packet)
      67             : {
      68         150 :     Msvideo1EncContext * const c = avctx->priv_data;
      69         150 :     const AVFrame *p = pict;
      70             :     uint16_t *src;
      71             :     uint8_t *prevptr;
      72             :     uint8_t *dst, *buf;
      73         150 :     int keyframe = 0;
      74         150 :     int no_skips = 1;
      75             :     int i, j, k, x, y, ret;
      76         150 :     int skips = 0;
      77         150 :     int quality = 24;
      78             : 
      79         150 :     if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*9 + AV_INPUT_BUFFER_MIN_SIZE, 0)) < 0)
      80           0 :         return ret;
      81         150 :     dst= buf= pkt->data;
      82             : 
      83         150 :     if(!c->prev)
      84           3 :         c->prev = av_malloc(avctx->width * 3 * (avctx->height + 3));
      85         150 :     prevptr = c->prev + avctx->width * 3 * (FFALIGN(avctx->height, 4) - 1);
      86         150 :     src = (uint16_t*)(p->data[0] + p->linesize[0]*(FFALIGN(avctx->height, 4) - 1));
      87         150 :     if(c->keyint >= avctx->keyint_min)
      88           6 :         keyframe = 1;
      89             : 
      90             : 
      91       10950 :     for(y = 0; y < avctx->height; y += 4){
      92      961200 :         for(x = 0; x < avctx->width; x += 4){
      93      950400 :             int bestmode = MODE_SKIP;
      94      950400 :             int bestscore = INT_MAX;
      95      950400 :             int flags = 0;
      96             :             int score;
      97             : 
      98     4752000 :             for(j = 0; j < 4; j++){
      99    19008000 :                 for(i = 0; i < 4; i++){
     100    15206400 :                     uint16_t val = src[x + i - j*p->linesize[0]/2];
     101    60825600 :                     for(k = 0; k < 3; k++){
     102    91238400 :                         c->block[(i + j*4)*3 + k] =
     103    91238400 :                         c->block2[remap[i + j*4]*3 + k] = (val >> (10-k*5)) & 0x1F;
     104             :                     }
     105             :                 }
     106             :             }
     107      950400 :             if(!keyframe){
     108      912384 :                 bestscore = 0;
     109     4561920 :                 for(j = 0; j < 4; j++){
     110    47443968 :                     for(i = 0; i < 4*3; i++){
     111    43794432 :                         int t = prevptr[x*3 + i - j*3*avctx->width] - c->block[i + j*4*3];
     112    43794432 :                         bestscore += t*t;
     113             :                     }
     114             :                 }
     115      912384 :                 bestscore /= quality;
     116             :             }
     117             :             // try to find optimal value to fill whole 4x4 block
     118      950400 :             score = 0;
     119      950400 :             avpriv_init_elbg(c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd);
     120      950400 :             avpriv_do_elbg  (c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd);
     121      950400 :             if(c->avg[0] == 1) // red component = 1 will be written as skip code
     122       12469 :                 c->avg[0] = 0;
     123     4752000 :             for(j = 0; j < 4; j++){
     124    19008000 :                 for(i = 0; i < 4; i++){
     125    60825600 :                     for(k = 0; k < 3; k++){
     126    45619200 :                         int t = c->avg[k] - c->block[(i+j*4)*3+k];
     127    45619200 :                         score += t*t;
     128             :                     }
     129             :                 }
     130             :             }
     131      950400 :             score /= quality;
     132      950400 :             score += 2;
     133      950400 :             if(score < bestscore){
     134      555268 :                 bestscore = score;
     135      555268 :                 bestmode = MODE_FILL;
     136             :             }
     137             :             // search for optimal filling of 2-color block
     138      950400 :             score = 0;
     139      950400 :             avpriv_init_elbg(c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd);
     140      950400 :             avpriv_do_elbg  (c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd);
     141             :             // last output value should be always 1, swap codebooks if needed
     142      950400 :             if(!c->output[15]){
     143     1485776 :                 for(i = 0; i < 3; i++)
     144     1114332 :                     FFSWAP(uint8_t, c->codebook[i], c->codebook[i+3]);
     145     6314548 :                 for(i = 0; i < 16; i++)
     146     5943104 :                     c->output[i] ^= 1;
     147             :             }
     148     4752000 :             for(j = 0; j < 4; j++){
     149    19008000 :                 for(i = 0; i < 4; i++){
     150    60825600 :                     for(k = 0; k < 3; k++){
     151    45619200 :                         int t = c->codebook[c->output[i+j*4]*3 + k] - c->block[i*3+k+j*4*3];
     152    45619200 :                         score += t*t;
     153             :                     }
     154             :                 }
     155             :             }
     156      950400 :             score /= quality;
     157      950400 :             score += 6;
     158      950400 :             if(score < bestscore){
     159      247307 :                 bestscore = score;
     160      247307 :                 bestmode = MODE_2COL;
     161             :             }
     162             :             // search for optimal filling of 2-color 2x2 subblocks
     163      950400 :             score = 0;
     164     4752000 :             for(i = 0; i < 4; i++){
     165     3801600 :                 avpriv_init_elbg(c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd);
     166     3801600 :                 avpriv_do_elbg  (c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd);
     167             :             }
     168             :             // last value should be always 1, swap codebooks if needed
     169      950400 :             if(!c->output2[15]){
     170     2270564 :                 for(i = 0; i < 3; i++)
     171     1702923 :                     FFSWAP(uint8_t, c->codebook2[i+18], c->codebook2[i+21]);
     172     2838205 :                 for(i = 12; i < 16; i++)
     173     2270564 :                     c->output2[i] ^= 1;
     174             :             }
     175     4752000 :             for(j = 0; j < 4; j++){
     176    19008000 :                 for(i = 0; i < 4; i++){
     177    60825600 :                     for(k = 0; k < 3; k++){
     178    45619200 :                         int t = c->codebook2[(c->output2[remap[i+j*4]] + (i&2) + (j&2)*2)*3+k] - c->block[i*3+k + j*4*3];
     179    45619200 :                         score += t*t;
     180             :                     }
     181             :                 }
     182             :             }
     183      950400 :             score /= quality;
     184      950400 :             score += 18;
     185      950400 :             if(score < bestscore){
     186      143607 :                 bestscore = score;
     187      143607 :                 bestmode = MODE_8COL;
     188             :             }
     189             : 
     190      950400 :             if(bestmode == MODE_SKIP){
     191      351933 :                 skips++;
     192      351933 :                 no_skips = 0;
     193             :             }
     194      950400 :             if((bestmode != MODE_SKIP && skips) || skips == SKIPS_MAX){
     195      107480 :                 bytestream_put_le16(&dst, skips | SKIP_PREFIX);
     196      107480 :                 skips = 0;
     197             :             }
     198             : 
     199      950400 :             switch(bestmode){
     200      320440 :             case MODE_FILL:
     201      320440 :                 bytestream_put_le16(&dst, MKRGB555(c->avg,0) | 0x8000);
     202     1602200 :                 for(j = 0; j < 4; j++)
     203     6408800 :                     for(i = 0; i < 4; i++)
     204    20508160 :                         for(k = 0; k < 3; k++)
     205    15381120 :                             prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->avg[k];
     206      320440 :                 break;
     207      134420 :             case MODE_2COL:
     208      672100 :                 for(j = 0; j < 4; j++){
     209     2688400 :                     for(i = 0; i < 4; i++){
     210     2150720 :                         flags |= (c->output[i + j*4]^1) << (i + j*4);
     211     8602880 :                         for(k = 0; k < 3; k++)
     212     6452160 :                             prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->codebook[c->output[i + j*4]*3 + k];
     213             :                     }
     214             :                 }
     215      134420 :                 bytestream_put_le16(&dst, flags);
     216      134420 :                 bytestream_put_le16(&dst, MKRGB555(c->codebook, 0));
     217      134420 :                 bytestream_put_le16(&dst, MKRGB555(c->codebook, 3));
     218      134420 :                 break;
     219      143607 :             case MODE_8COL:
     220      718035 :                 for(j = 0; j < 4; j++){
     221     2872140 :                     for(i = 0; i < 4; i++){
     222     2297712 :                         flags |= (c->output2[remap[i + j*4]]^1) << (i + j*4);
     223     9190848 :                         for(k = 0; k < 3; k++)
     224     6893136 :                             prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->codebook2[(c->output2[remap[i+j*4]] + (i&2) + (j&2)*2)*3 + k];
     225             :                     }
     226             :                 }
     227      143607 :                 bytestream_put_le16(&dst, flags);
     228      143607 :                 bytestream_put_le16(&dst, MKRGB555(c->codebook2, 0) | 0x8000);
     229     1148856 :                 for(i = 3; i < 24; i += 3)
     230     1005249 :                     bytestream_put_le16(&dst, MKRGB555(c->codebook2, i));
     231      143607 :                 break;
     232             :             }
     233             :         }
     234       10800 :         src     -= p->linesize[0] << 1;
     235       10800 :         prevptr -= avctx->width * 3 * 4;
     236             :     }
     237         150 :     if(skips)
     238          29 :         bytestream_put_le16(&dst, skips | SKIP_PREFIX);
     239             :     //EOF
     240         150 :     bytestream_put_byte(&dst, 0);
     241         150 :     bytestream_put_byte(&dst, 0);
     242             : 
     243         150 :     if(no_skips)
     244           6 :         keyframe = 1;
     245         150 :     if(keyframe)
     246           6 :         c->keyint = 0;
     247             :     else
     248         144 :         c->keyint++;
     249         150 :     if (keyframe) pkt->flags |= AV_PKT_FLAG_KEY;
     250         150 :     pkt->size = dst - buf;
     251         150 :     *got_packet = 1;
     252             : 
     253         150 :     return 0;
     254             : }
     255             : 
     256             : 
     257             : /**
     258             :  * init encoder
     259             :  */
     260           3 : static av_cold int encode_init(AVCodecContext *avctx)
     261             : {
     262           3 :     Msvideo1EncContext * const c = avctx->priv_data;
     263             : 
     264           3 :     c->avctx = avctx;
     265           3 :     if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
     266           0 :         return -1;
     267             :     }
     268           3 :     if((avctx->width&3) || (avctx->height&3)){
     269           0 :         av_log(avctx, AV_LOG_ERROR, "width and height must be multiples of 4\n");
     270           0 :         return -1;
     271             :     }
     272             : 
     273           3 :     avctx->bits_per_coded_sample = 16;
     274             : 
     275           3 :     c->keyint = avctx->keyint_min;
     276           3 :     av_lfg_init(&c->rnd, 1);
     277             : 
     278           3 :     return 0;
     279             : }
     280             : 
     281             : 
     282             : 
     283             : /**
     284             :  * Uninit encoder
     285             :  */
     286           3 : static av_cold int encode_end(AVCodecContext *avctx)
     287             : {
     288           3 :     Msvideo1EncContext * const c = avctx->priv_data;
     289             : 
     290           3 :     av_freep(&c->prev);
     291             : 
     292           3 :     return 0;
     293             : }
     294             : 
     295             : AVCodec ff_msvideo1_encoder = {
     296             :     .name           = "msvideo1",
     297             :     .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video-1"),
     298             :     .type           = AVMEDIA_TYPE_VIDEO,
     299             :     .id             = AV_CODEC_ID_MSVIDEO1,
     300             :     .priv_data_size = sizeof(Msvideo1EncContext),
     301             :     .init           = encode_init,
     302             :     .encode2        = encode_frame,
     303             :     .close          = encode_end,
     304             :     .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB555, AV_PIX_FMT_NONE},
     305             : };

Generated by: LCOV version 1.13