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 */
37typedef 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
54enum 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
65static const int remap[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 };
66
67static 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 */
269static 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 */
295static 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
305const 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