annotate ffmpeg/libavcodec/msvideo1enc.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Microsoft Video-1 Encoder
yading@10 3 * Copyright (c) 2009 Konstantin Shishkov
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * Microsoft Video-1 encoder
yading@10 25 */
yading@10 26
yading@10 27 #include "avcodec.h"
yading@10 28 #include "internal.h"
yading@10 29 #include "bytestream.h"
yading@10 30 #include "libavutil/lfg.h"
yading@10 31 #include "elbg.h"
yading@10 32 #include "libavutil/imgutils.h"
yading@10 33 /**
yading@10 34 * Encoder context
yading@10 35 */
yading@10 36 typedef struct Msvideo1EncContext {
yading@10 37 AVCodecContext *avctx;
yading@10 38 AVFrame pic;
yading@10 39 AVLFG rnd;
yading@10 40 uint8_t *prev;
yading@10 41
yading@10 42 int block[16*3];
yading@10 43 int block2[16*3];
yading@10 44 int codebook[8*3];
yading@10 45 int codebook2[8*3];
yading@10 46 int output[16*3];
yading@10 47 int output2[16*3];
yading@10 48 int avg[3];
yading@10 49 int bestpos;
yading@10 50 int keyint;
yading@10 51 } Msvideo1EncContext;
yading@10 52
yading@10 53 enum MSV1Mode{
yading@10 54 MODE_SKIP = 0,
yading@10 55 MODE_FILL,
yading@10 56 MODE_2COL,
yading@10 57 MODE_8COL,
yading@10 58 };
yading@10 59
yading@10 60 #define SKIP_PREFIX 0x8400
yading@10 61 #define SKIPS_MAX 0x0FFF
yading@10 62 #define MKRGB555(in, off) ((in[off] << 10) | (in[off + 1] << 5) | (in[off + 2]))
yading@10 63
yading@10 64 static const int remap[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 };
yading@10 65
yading@10 66 static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
yading@10 67 const AVFrame *pict, int *got_packet)
yading@10 68 {
yading@10 69 Msvideo1EncContext * const c = avctx->priv_data;
yading@10 70 AVFrame * const p = &c->pic;
yading@10 71 uint16_t *src;
yading@10 72 uint8_t *prevptr;
yading@10 73 uint8_t *dst, *buf;
yading@10 74 int keyframe = 0;
yading@10 75 int no_skips = 1;
yading@10 76 int i, j, k, x, y, ret;
yading@10 77 int skips = 0;
yading@10 78
yading@10 79 if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*9 + FF_MIN_BUFFER_SIZE)) < 0)
yading@10 80 return ret;
yading@10 81 dst= buf= pkt->data;
yading@10 82
yading@10 83 *p = *pict;
yading@10 84 if(!c->prev)
yading@10 85 c->prev = av_malloc(avctx->width * 3 * (avctx->height + 3));
yading@10 86 prevptr = c->prev + avctx->width * 3 * (FFALIGN(avctx->height, 4) - 1);
yading@10 87 src = (uint16_t*)(p->data[0] + p->linesize[0]*(FFALIGN(avctx->height, 4) - 1));
yading@10 88 if(c->keyint >= avctx->keyint_min)
yading@10 89 keyframe = 1;
yading@10 90
yading@10 91 p->quality = 24;
yading@10 92
yading@10 93 for(y = 0; y < avctx->height; y += 4){
yading@10 94 for(x = 0; x < avctx->width; x += 4){
yading@10 95 int bestmode = MODE_SKIP;
yading@10 96 int bestscore = INT_MAX;
yading@10 97 int flags = 0;
yading@10 98 int score;
yading@10 99
yading@10 100 for(j = 0; j < 4; j++){
yading@10 101 for(i = 0; i < 4; i++){
yading@10 102 uint16_t val = src[x + i - j*p->linesize[0]/2];
yading@10 103 for(k = 0; k < 3; k++){
yading@10 104 c->block[(i + j*4)*3 + k] =
yading@10 105 c->block2[remap[i + j*4]*3 + k] = (val >> (10-k*5)) & 0x1F;
yading@10 106 }
yading@10 107 }
yading@10 108 }
yading@10 109 if(!keyframe){
yading@10 110 bestscore = 0;
yading@10 111 for(j = 0; j < 4; j++){
yading@10 112 for(i = 0; i < 4*3; i++){
yading@10 113 int t = prevptr[x*3 + i - j*3*avctx->width] - c->block[i + j*4*3];
yading@10 114 bestscore += t*t;
yading@10 115 }
yading@10 116 }
yading@10 117 bestscore /= p->quality;
yading@10 118 }
yading@10 119 // try to find optimal value to fill whole 4x4 block
yading@10 120 score = 0;
yading@10 121 ff_init_elbg(c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd);
yading@10 122 ff_do_elbg (c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd);
yading@10 123 if(c->avg[0] == 1) // red component = 1 will be written as skip code
yading@10 124 c->avg[0] = 0;
yading@10 125 for(j = 0; j < 4; j++){
yading@10 126 for(i = 0; i < 4; i++){
yading@10 127 for(k = 0; k < 3; k++){
yading@10 128 int t = c->avg[k] - c->block[(i+j*4)*3+k];
yading@10 129 score += t*t;
yading@10 130 }
yading@10 131 }
yading@10 132 }
yading@10 133 score /= p->quality;
yading@10 134 score += 2;
yading@10 135 if(score < bestscore){
yading@10 136 bestscore = score;
yading@10 137 bestmode = MODE_FILL;
yading@10 138 }
yading@10 139 // search for optimal filling of 2-color block
yading@10 140 score = 0;
yading@10 141 ff_init_elbg(c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd);
yading@10 142 ff_do_elbg (c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd);
yading@10 143 // last output value should be always 1, swap codebooks if needed
yading@10 144 if(!c->output[15]){
yading@10 145 for(i = 0; i < 3; i++)
yading@10 146 FFSWAP(uint8_t, c->codebook[i], c->codebook[i+3]);
yading@10 147 for(i = 0; i < 16; i++)
yading@10 148 c->output[i] ^= 1;
yading@10 149 }
yading@10 150 for(j = 0; j < 4; j++){
yading@10 151 for(i = 0; i < 4; i++){
yading@10 152 for(k = 0; k < 3; k++){
yading@10 153 int t = c->codebook[c->output[i+j*4]*3 + k] - c->block[i*3+k+j*4*3];
yading@10 154 score += t*t;
yading@10 155 }
yading@10 156 }
yading@10 157 }
yading@10 158 score /= p->quality;
yading@10 159 score += 6;
yading@10 160 if(score < bestscore){
yading@10 161 bestscore = score;
yading@10 162 bestmode = MODE_2COL;
yading@10 163 }
yading@10 164 // search for optimal filling of 2-color 2x2 subblocks
yading@10 165 score = 0;
yading@10 166 for(i = 0; i < 4; i++){
yading@10 167 ff_init_elbg(c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd);
yading@10 168 ff_do_elbg (c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd);
yading@10 169 }
yading@10 170 // last value should be always 1, swap codebooks if needed
yading@10 171 if(!c->output2[15]){
yading@10 172 for(i = 0; i < 3; i++)
yading@10 173 FFSWAP(uint8_t, c->codebook2[i+18], c->codebook2[i+21]);
yading@10 174 for(i = 12; i < 16; i++)
yading@10 175 c->output2[i] ^= 1;
yading@10 176 }
yading@10 177 for(j = 0; j < 4; j++){
yading@10 178 for(i = 0; i < 4; i++){
yading@10 179 for(k = 0; k < 3; k++){
yading@10 180 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];
yading@10 181 score += t*t;
yading@10 182 }
yading@10 183 }
yading@10 184 }
yading@10 185 score /= p->quality;
yading@10 186 score += 18;
yading@10 187 if(score < bestscore){
yading@10 188 bestscore = score;
yading@10 189 bestmode = MODE_8COL;
yading@10 190 }
yading@10 191
yading@10 192 if(bestmode == MODE_SKIP){
yading@10 193 skips++;
yading@10 194 no_skips = 0;
yading@10 195 }
yading@10 196 if((bestmode != MODE_SKIP && skips) || skips == SKIPS_MAX){
yading@10 197 bytestream_put_le16(&dst, skips | SKIP_PREFIX);
yading@10 198 skips = 0;
yading@10 199 }
yading@10 200
yading@10 201 switch(bestmode){
yading@10 202 case MODE_FILL:
yading@10 203 bytestream_put_le16(&dst, MKRGB555(c->avg,0) | 0x8000);
yading@10 204 for(j = 0; j < 4; j++)
yading@10 205 for(i = 0; i < 4; i++)
yading@10 206 for(k = 0; k < 3; k++)
yading@10 207 prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->avg[k];
yading@10 208 break;
yading@10 209 case MODE_2COL:
yading@10 210 for(j = 0; j < 4; j++){
yading@10 211 for(i = 0; i < 4; i++){
yading@10 212 flags |= (c->output[i + j*4]^1) << (i + j*4);
yading@10 213 for(k = 0; k < 3; k++)
yading@10 214 prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->codebook[c->output[i + j*4]*3 + k];
yading@10 215 }
yading@10 216 }
yading@10 217 bytestream_put_le16(&dst, flags);
yading@10 218 bytestream_put_le16(&dst, MKRGB555(c->codebook, 0));
yading@10 219 bytestream_put_le16(&dst, MKRGB555(c->codebook, 3));
yading@10 220 break;
yading@10 221 case MODE_8COL:
yading@10 222 for(j = 0; j < 4; j++){
yading@10 223 for(i = 0; i < 4; i++){
yading@10 224 flags |= (c->output2[remap[i + j*4]]^1) << (i + j*4);
yading@10 225 for(k = 0; k < 3; k++)
yading@10 226 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];
yading@10 227 }
yading@10 228 }
yading@10 229 bytestream_put_le16(&dst, flags);
yading@10 230 bytestream_put_le16(&dst, MKRGB555(c->codebook2, 0) | 0x8000);
yading@10 231 for(i = 3; i < 24; i += 3)
yading@10 232 bytestream_put_le16(&dst, MKRGB555(c->codebook2, i));
yading@10 233 break;
yading@10 234 }
yading@10 235 }
yading@10 236 src -= p->linesize[0] << 1;
yading@10 237 prevptr -= avctx->width * 3 * 4;
yading@10 238 }
yading@10 239 if(skips)
yading@10 240 bytestream_put_le16(&dst, skips | SKIP_PREFIX);
yading@10 241 //EOF
yading@10 242 bytestream_put_byte(&dst, 0);
yading@10 243 bytestream_put_byte(&dst, 0);
yading@10 244
yading@10 245 if(no_skips)
yading@10 246 keyframe = 1;
yading@10 247 if(keyframe)
yading@10 248 c->keyint = 0;
yading@10 249 else
yading@10 250 c->keyint++;
yading@10 251 p->pict_type= keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
yading@10 252 p->key_frame= keyframe;
yading@10 253 if (keyframe) pkt->flags |= AV_PKT_FLAG_KEY;
yading@10 254 pkt->size = dst - buf;
yading@10 255 *got_packet = 1;
yading@10 256
yading@10 257 return 0;
yading@10 258 }
yading@10 259
yading@10 260
yading@10 261 /**
yading@10 262 * init encoder
yading@10 263 */
yading@10 264 static av_cold int encode_init(AVCodecContext *avctx)
yading@10 265 {
yading@10 266 Msvideo1EncContext * const c = avctx->priv_data;
yading@10 267
yading@10 268 c->avctx = avctx;
yading@10 269 if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
yading@10 270 return -1;
yading@10 271 }
yading@10 272 if((avctx->width&3) || (avctx->height&3)){
yading@10 273 av_log(avctx, AV_LOG_ERROR, "width and height must be multiplies of 4\n");
yading@10 274 return -1;
yading@10 275 }
yading@10 276
yading@10 277 avcodec_get_frame_defaults(&c->pic);
yading@10 278 avctx->coded_frame = (AVFrame*)&c->pic;
yading@10 279 avctx->bits_per_coded_sample = 16;
yading@10 280
yading@10 281 c->keyint = avctx->keyint_min;
yading@10 282 av_lfg_init(&c->rnd, 1);
yading@10 283
yading@10 284 return 0;
yading@10 285 }
yading@10 286
yading@10 287
yading@10 288
yading@10 289 /**
yading@10 290 * Uninit encoder
yading@10 291 */
yading@10 292 static av_cold int encode_end(AVCodecContext *avctx)
yading@10 293 {
yading@10 294 Msvideo1EncContext * const c = avctx->priv_data;
yading@10 295
yading@10 296 av_freep(&c->prev);
yading@10 297
yading@10 298 return 0;
yading@10 299 }
yading@10 300
yading@10 301 AVCodec ff_msvideo1_encoder = {
yading@10 302 .name = "msvideo1",
yading@10 303 .type = AVMEDIA_TYPE_VIDEO,
yading@10 304 .id = AV_CODEC_ID_MSVIDEO1,
yading@10 305 .priv_data_size = sizeof(Msvideo1EncContext),
yading@10 306 .init = encode_init,
yading@10 307 .encode2 = encode_frame,
yading@10 308 .close = encode_end,
yading@10 309 .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB555, AV_PIX_FMT_NONE},
yading@10 310 .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video-1"),
yading@10 311 };