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