]> git.sesse.net Git - ffmpeg/blob - libavcodec/msvideo1enc.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / msvideo1enc.c
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 "bytestream.h"
29 #include "libavutil/lfg.h"
30 #include "elbg.h"
31 #include "libavutil/imgutils.h"
32 /**
33  * Encoder context
34  */
35 typedef struct Msvideo1EncContext {
36     AVCodecContext *avctx;
37     AVFrame pic;
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 0x0FFF
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 static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
66 {
67     Msvideo1EncContext * const c = avctx->priv_data;
68     AVFrame *pict = data;
69     AVFrame * const p = &c->pic;
70     uint16_t *src;
71     uint8_t *prevptr;
72     uint8_t *dst = buf;
73     int keyframe = 1;
74     int no_skips = 1;
75     int i, j, k, x, y;
76     int skips = 0;
77
78     *p = *pict;
79     if(!c->prev)
80         c->prev = av_malloc(avctx->width * 3 * (avctx->height + 3));
81     prevptr = c->prev + avctx->width * 3 * (FFALIGN(avctx->height, 4) - 1);
82     src = (uint16_t*)(p->data[0] + p->linesize[0]*(FFALIGN(avctx->height, 4) - 1));
83     if(c->keyint >= avctx->keyint_min)
84         keyframe = 1;
85
86     p->quality = 24;
87
88     for(y = 0; y < avctx->height; y += 4){
89         for(x = 0; x < avctx->width; x += 4){
90             int bestmode = MODE_SKIP;
91             int bestscore = INT_MAX;
92             int flags = 0;
93             int score;
94
95             for(j = 0; j < 4; j++){
96                 for(i = 0; i < 4; i++){
97                     uint16_t val = src[x + i - j*p->linesize[0]/2];
98                     for(k = 0; k < 3; k++){
99                         c->block[(i + j*4)*3 + k] =
100                         c->block2[remap[i + j*4]*3 + k] = (val >> (10-k*5)) & 0x1F;
101                     }
102                 }
103             }
104             if(!keyframe){
105                 bestscore = 0;
106                 for(j = 0; j < 4; j++){
107                     for(i = 0; i < 4*3; i++){
108                         int t = prevptr[x*3 + i + j*p->linesize[0]] - c->block[i + j*4*3];
109                         bestscore += t*t;
110                     }
111                 }
112                 bestscore /= p->quality;
113             }
114             // try to find optimal value to fill whole 4x4 block
115             score = 0;
116             ff_init_elbg(c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd);
117             ff_do_elbg  (c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd);
118             if(c->avg[0] == 1) // red component = 1 will be written as skip code
119                 c->avg[0] = 0;
120             for(j = 0; j < 4; j++){
121                 for(i = 0; i < 4; i++){
122                     for(k = 0; k < 3; k++){
123                         int t = c->avg[k] - c->block[(i+j*4)*3+k];
124                         score += t*t;
125                     }
126                 }
127             }
128             score /= p->quality;
129             score += 2;
130             if(score < bestscore){
131                 bestscore = score;
132                 bestmode = MODE_FILL;
133             }
134             // search for optimal filling of 2-color block
135             score = 0;
136             ff_init_elbg(c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd);
137             ff_do_elbg  (c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd);
138             // last output value should be always 1, swap codebooks if needed
139             if(!c->output[15]){
140                 for(i = 0; i < 3; i++)
141                     FFSWAP(uint8_t, c->codebook[i], c->codebook[i+3]);
142                 for(i = 0; i < 16; i++)
143                     c->output[i] ^= 1;
144             }
145             for(j = 0; j < 4; j++){
146                 for(i = 0; i < 4; i++){
147                     for(k = 0; k < 3; k++){
148                         int t = c->codebook[c->output[i+j*4]*3 + k] - c->block[i*3+k+j*4*3];
149                         score += t*t;
150                     }
151                 }
152             }
153             score /= p->quality;
154             score += 6;
155             if(score < bestscore){
156                 bestscore = score;
157                 bestmode = MODE_2COL;
158             }
159             // search for optimal filling of 2-color 2x2 subblocks
160             score = 0;
161             for(i = 0; i < 4; i++){
162                 ff_init_elbg(c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd);
163                 ff_do_elbg  (c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd);
164             }
165             // last value should be always 1, swap codebooks if needed
166             if(!c->output2[15]){
167                 for(i = 0; i < 3; i++)
168                     FFSWAP(uint8_t, c->codebook2[i+18], c->codebook2[i+21]);
169                 for(i = 12; i < 16; i++)
170                     c->output2[i] ^= 1;
171             }
172             for(j = 0; j < 4; j++){
173                 for(i = 0; i < 4; i++){
174                     for(k = 0; k < 3; k++){
175                         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];
176                         score += t*t;
177                     }
178                 }
179             }
180             score /= p->quality;
181             score += 18;
182             if(score < bestscore){
183                 bestscore = score;
184                 bestmode = MODE_8COL;
185             }
186
187             if(bestmode == MODE_SKIP){
188                 skips++;
189                 no_skips = 0;
190             }
191             if((bestmode != MODE_SKIP && skips) || skips == SKIPS_MAX){
192                 bytestream_put_le16(&dst, skips | SKIP_PREFIX);
193                 skips = 0;
194             }
195
196             switch(bestmode){
197             case MODE_FILL:
198                 bytestream_put_le16(&dst, MKRGB555(c->avg,0) | 0x8000);
199                 for(j = 0; j < 4; j++)
200                     for(i = 0; i < 4; i++)
201                         for(k = 0; k < 3; k++)
202                             prevptr[i*3 + k - j*3*avctx->width] = c->avg[k];
203                 break;
204             case MODE_2COL:
205                 for(j = 0; j < 4; j++){
206                     for(i = 0; i < 4; i++){
207                         flags |= (c->output[i + j*4]^1) << (i + j*4);
208                         for(k = 0; k < 3; k++)
209                             prevptr[i*3 + k - j*3*avctx->width] = c->codebook[c->output[i + j*4]*3 + k];
210                     }
211                 }
212                 bytestream_put_le16(&dst, flags);
213                 bytestream_put_le16(&dst, MKRGB555(c->codebook, 0));
214                 bytestream_put_le16(&dst, MKRGB555(c->codebook, 3));
215                 break;
216             case MODE_8COL:
217                 for(j = 0; j < 4; j++){
218                     for(i = 0; i < 4; i++){
219                         flags |= (c->output2[remap[i + j*4]]^1) << (i + j*4);
220                         for(k = 0; k < 3; k++)
221                             prevptr[i*3 + k - j*3*avctx->width] = c->codebook2[(c->output2[remap[i+j*4]] + (i&2) + (j&2)*2)*3 + k];
222                     }
223                 }
224                 bytestream_put_le16(&dst, flags);
225                 bytestream_put_le16(&dst, MKRGB555(c->codebook2, 0) | 0x8000);
226                 for(i = 3; i < 24; i += 3)
227                     bytestream_put_le16(&dst, MKRGB555(c->codebook2, i));
228                 break;
229             }
230         }
231         src     -= p->linesize[0] << 1;
232         prevptr -= avctx->width * 3 * 4;
233     }
234     if(skips)
235         bytestream_put_le16(&dst, skips | SKIP_PREFIX);
236     //EOF
237     bytestream_put_byte(&dst, 0);
238     bytestream_put_byte(&dst, 0);
239
240     if(no_skips)
241         keyframe = 1;
242     if(keyframe)
243         c->keyint = 0;
244     else
245         c->keyint++;
246     p->pict_type= keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
247     p->key_frame= keyframe;
248
249     return dst - buf;
250 }
251
252
253 /**
254  * init encoder
255  */
256 static av_cold int encode_init(AVCodecContext *avctx)
257 {
258     Msvideo1EncContext * const c = avctx->priv_data;
259
260     c->avctx = avctx;
261     if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
262         return -1;
263     }
264     if((avctx->width&3) || (avctx->height&3)){
265         av_log(avctx, AV_LOG_ERROR, "width and height must be multiplies of 4\n");
266         return -1;
267     }
268
269     avcodec_get_frame_defaults(&c->pic);
270     avctx->coded_frame = (AVFrame*)&c->pic;
271
272     c->keyint = avctx->keyint_min;
273     av_lfg_init(&c->rnd, 1);
274
275     return 0;
276 }
277
278
279
280 /**
281  * Uninit encoder
282  */
283 static av_cold int encode_end(AVCodecContext *avctx)
284 {
285     Msvideo1EncContext * const c = avctx->priv_data;
286
287     av_freep(&c->prev);
288
289     return 0;
290 }
291
292 AVCodec ff_msvideo1_encoder = {
293     .name           = "msvideo1",
294     .type           = AVMEDIA_TYPE_VIDEO,
295     .id             = CODEC_ID_MSVIDEO1,
296     .priv_data_size = sizeof(Msvideo1EncContext),
297     .init           = encode_init,
298     .encode         = encode_frame,
299     .close          = encode_end,
300     .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB555, PIX_FMT_NONE},
301     .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video-1"),
302 };