00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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)
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
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
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
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
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
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 };