• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/msvideo1enc.c

Go to the documentation of this file.
00001 /*
00002  * Microsoft Video-1 Encoder
00003  * Copyright (c) 2009 Konstantin Shishkov
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 #include "avcodec.h"
00028 #include "bytestream.h"
00029 #include "libavutil/lfg.h"
00030 #include "elbg.h"
00031 #include "libavutil/imgutils.h"
00035 typedef struct Msvideo1EncContext {
00036     AVCodecContext *avctx;
00037     AVFrame pic;
00038     AVLFG rnd;
00039     uint8_t *prev;
00040 
00041     int block[16*3];
00042     int block2[16*3];
00043     int codebook[8*3];
00044     int codebook2[8*3];
00045     int output[16*3];
00046     int output2[16*3];
00047     int avg[3];
00048     int bestpos;
00049     int keyint;
00050 } Msvideo1EncContext;
00051 
00052 enum MSV1Mode{
00053     MODE_SKIP = 0,
00054     MODE_FILL,
00055     MODE_2COL,
00056     MODE_8COL,
00057 };
00058 
00059 #define SKIP_PREFIX 0x8400
00060 #define SKIPS_MAX 0x0FFF
00061 #define MKRGB555(in, off) ((in[off] << 10) | (in[off + 1] << 5) | (in[off + 2]))
00062 
00063 static const int remap[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 };
00064 
00065 static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
00066 {
00067     Msvideo1EncContext * const c = avctx->priv_data;
00068     AVFrame *pict = data;
00069     AVFrame * const p = &c->pic;
00070     uint16_t *src;
00071     uint8_t *prevptr;
00072     uint8_t *dst = buf;
00073     int keyframe = 1;
00074     int no_skips = 1;
00075     int i, j, k, x, y;
00076     int skips = 0;
00077 
00078     *p = *pict;
00079     if(!c->prev)
00080         c->prev = av_malloc(avctx->width * 3 * (avctx->height + 3));
00081     prevptr = c->prev + avctx->width * 3 * (FFALIGN(avctx->height, 4) - 1);
00082     src = (uint16_t*)(p->data[0] + p->linesize[0]*(FFALIGN(avctx->height, 4) - 1));
00083     if(c->keyint >= avctx->keyint_min)
00084         keyframe = 1;
00085 
00086     p->quality = 24;
00087 
00088     for(y = 0; y < avctx->height; y += 4){
00089         for(x = 0; x < avctx->width; x += 4){
00090             int bestmode = MODE_SKIP;
00091             int bestscore = INT_MAX;
00092             int flags = 0;
00093             int score;
00094 
00095             for(j = 0; j < 4; j++){
00096                 for(i = 0; i < 4; i++){
00097                     uint16_t val = src[x + i - j*p->linesize[0]/2];
00098                     for(k = 0; k < 3; k++){
00099                         c->block[(i + j*4)*3 + k] =
00100                         c->block2[remap[i + j*4]*3 + k] = (val >> (10-k*5)) & 0x1F;
00101                     }
00102                 }
00103             }
00104             if(!keyframe){
00105                 bestscore = 0;
00106                 for(j = 0; j < 4; j++){
00107                     for(i = 0; i < 4*3; i++){
00108                         int t = prevptr[x*3 + i + j*p->linesize[0]] - c->block[i + j*4*3];
00109                         bestscore += t*t;
00110                     }
00111                 }
00112                 bestscore /= p->quality;
00113             }
00114             // try to find optimal value to fill whole 4x4 block
00115             score = 0;
00116             ff_init_elbg(c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd);
00117             ff_do_elbg  (c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd);
00118             if(c->avg[0] == 1) // red component = 1 will be written as skip code
00119                 c->avg[0] = 0;
00120             for(j = 0; j < 4; j++){
00121                 for(i = 0; i < 4; i++){
00122                     for(k = 0; k < 3; k++){
00123                         int t = c->avg[k] - c->block[(i+j*4)*3+k];
00124                         score += t*t;
00125                     }
00126                 }
00127             }
00128             score /= p->quality;
00129             score += 2;
00130             if(score < bestscore){
00131                 bestscore = score;
00132                 bestmode = MODE_FILL;
00133             }
00134             // search for optimal filling of 2-color block
00135             score = 0;
00136             ff_init_elbg(c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd);
00137             ff_do_elbg  (c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd);
00138             // last output value should be always 1, swap codebooks if needed
00139             if(!c->output[15]){
00140                 for(i = 0; i < 3; i++)
00141                     FFSWAP(uint8_t, c->codebook[i], c->codebook[i+3]);
00142                 for(i = 0; i < 16; i++)
00143                     c->output[i] ^= 1;
00144             }
00145             for(j = 0; j < 4; j++){
00146                 for(i = 0; i < 4; i++){
00147                     for(k = 0; k < 3; k++){
00148                         int t = c->codebook[c->output[i+j*4]*3 + k] - c->block[i*3+k+j*4*3];
00149                         score += t*t;
00150                     }
00151                 }
00152             }
00153             score /= p->quality;
00154             score += 6;
00155             if(score < bestscore){
00156                 bestscore = score;
00157                 bestmode = MODE_2COL;
00158             }
00159             // search for optimal filling of 2-color 2x2 subblocks
00160             score = 0;
00161             for(i = 0; i < 4; i++){
00162                 ff_init_elbg(c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd);
00163                 ff_do_elbg  (c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd);
00164             }
00165             // last value should be always 1, swap codebooks if needed
00166             if(!c->output2[15]){
00167                 for(i = 0; i < 3; i++)
00168                     FFSWAP(uint8_t, c->codebook2[i+18], c->codebook2[i+21]);
00169                 for(i = 12; i < 16; i++)
00170                     c->output2[i] ^= 1;
00171             }
00172             for(j = 0; j < 4; j++){
00173                 for(i = 0; i < 4; i++){
00174                     for(k = 0; k < 3; k++){
00175                         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];
00176                         score += t*t;
00177                     }
00178                 }
00179             }
00180             score /= p->quality;
00181             score += 18;
00182             if(score < bestscore){
00183                 bestscore = score;
00184                 bestmode = MODE_8COL;
00185             }
00186 
00187             if(bestmode == MODE_SKIP){
00188                 skips++;
00189                 no_skips = 0;
00190             }
00191             if((bestmode != MODE_SKIP && skips) || skips == SKIPS_MAX){
00192                 bytestream_put_le16(&dst, skips | SKIP_PREFIX);
00193                 skips = 0;
00194             }
00195 
00196             switch(bestmode){
00197             case MODE_FILL:
00198                 bytestream_put_le16(&dst, MKRGB555(c->avg,0) | 0x8000);
00199                 for(j = 0; j < 4; j++)
00200                     for(i = 0; i < 4; i++)
00201                         for(k = 0; k < 3; k++)
00202                             prevptr[i*3 + k - j*3*avctx->width] = c->avg[k];
00203                 break;
00204             case MODE_2COL:
00205                 for(j = 0; j < 4; j++){
00206                     for(i = 0; i < 4; i++){
00207                         flags |= (c->output[i + j*4]^1) << (i + j*4);
00208                         for(k = 0; k < 3; k++)
00209                             prevptr[i*3 + k - j*3*avctx->width] = c->codebook[c->output[i + j*4]*3 + k];
00210                     }
00211                 }
00212                 bytestream_put_le16(&dst, flags);
00213                 bytestream_put_le16(&dst, MKRGB555(c->codebook, 0));
00214                 bytestream_put_le16(&dst, MKRGB555(c->codebook, 3));
00215                 break;
00216             case MODE_8COL:
00217                 for(j = 0; j < 4; j++){
00218                     for(i = 0; i < 4; i++){
00219                         flags |= (c->output2[remap[i + j*4]]^1) << (i + j*4);
00220                         for(k = 0; k < 3; k++)
00221                             prevptr[i*3 + k - j*3*avctx->width] = c->codebook2[(c->output2[remap[i+j*4]] + (i&2) + (j&2)*2)*3 + k];
00222                     }
00223                 }
00224                 bytestream_put_le16(&dst, flags);
00225                 bytestream_put_le16(&dst, MKRGB555(c->codebook2, 0) | 0x8000);
00226                 for(i = 3; i < 24; i += 3)
00227                     bytestream_put_le16(&dst, MKRGB555(c->codebook2, i));
00228                 break;
00229             }
00230         }
00231         src     -= p->linesize[0] << 1;
00232         prevptr -= avctx->width * 3 * 4;
00233     }
00234     if(skips)
00235         bytestream_put_le16(&dst, skips | SKIP_PREFIX);
00236     //EOF
00237     bytestream_put_byte(&dst, 0);
00238     bytestream_put_byte(&dst, 0);
00239 
00240     if(no_skips)
00241         keyframe = 1;
00242     if(keyframe)
00243         c->keyint = 0;
00244     else
00245         c->keyint++;
00246     p->pict_type= keyframe ? FF_I_TYPE : FF_P_TYPE;
00247     p->key_frame= keyframe;
00248 
00249     return dst - buf;
00250 }
00251 
00252 
00256 static av_cold int encode_init(AVCodecContext *avctx)
00257 {
00258     Msvideo1EncContext * const c = avctx->priv_data;
00259 
00260     c->avctx = avctx;
00261     if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
00262         return -1;
00263     }
00264 
00265     avcodec_get_frame_defaults(&c->pic);
00266     avctx->coded_frame = (AVFrame*)&c->pic;
00267 
00268     c->keyint = avctx->keyint_min;
00269     av_lfg_init(&c->rnd, 1);
00270 
00271     return 0;
00272 }
00273 
00274 
00275 
00279 static av_cold int encode_end(AVCodecContext *avctx)
00280 {
00281     Msvideo1EncContext * const c = avctx->priv_data;
00282 
00283     av_freep(&c->prev);
00284 
00285     return 0;
00286 }
00287 
00288 AVCodec ff_msvideo1_encoder = {
00289     "msvideo1",
00290     AVMEDIA_TYPE_VIDEO,
00291     CODEC_ID_MSVIDEO1,
00292     sizeof(Msvideo1EncContext),
00293     encode_init,
00294     encode_frame,
00295     encode_end,
00296     .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB555, PIX_FMT_NONE},
00297     .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video-1"),
00298 };

Generated on Wed Apr 11 2012 07:31:34 for FFmpeg by  doxygen 1.7.1