2 * Microsoft Video-1 Encoder
3 * Copyright (c) 2009 Konstantin Shishkov
5 * This file is part of FFmpeg.
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.
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.
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
24 * Microsoft Video-1 encoder
29 #include "bytestream.h"
30 #include "libavutil/lfg.h"
32 #include "libavutil/imgutils.h"
36 typedef struct Msvideo1EncContext
{
37 AVCodecContext
*avctx
;
59 #define SKIP_PREFIX 0x8400
60 #define SKIPS_MAX 0x03FF
61 #define MKRGB555(in, off) (((in)[off] << 10) | ((in)[(off) + 1] << 5) | ((in)[(off) + 2]))
63 static const int remap
[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 };
65 static int encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
66 const AVFrame
*pict
, int *got_packet
)
68 Msvideo1EncContext
* const c
= avctx
->priv_data
;
69 const AVFrame
*p
= pict
;
75 int i
, j
, k
, x
, y
, ret
;
79 if ((ret
= ff_alloc_packet2(avctx
, pkt
, avctx
->width
*avctx
->height
*9 + FF_MIN_BUFFER_SIZE
)) < 0)
84 c
->prev
= av_malloc(avctx
->width
* 3 * (avctx
->height
+ 3));
85 prevptr
= c
->prev
+ avctx
->width
* 3 * (FFALIGN(avctx
->height
, 4) - 1);
86 src
= (uint16_t*)(p
->data
[0] + p
->linesize
[0]*(FFALIGN(avctx
->height
, 4) - 1));
87 if(c
->keyint
>= avctx
->keyint_min
)
91 for(y
= 0; y
< avctx
->height
; y
+= 4){
92 for(x
= 0; x
< avctx
->width
; x
+= 4){
93 int bestmode
= MODE_SKIP
;
94 int bestscore
= INT_MAX
;
98 for(j
= 0; j
< 4; j
++){
99 for(i
= 0; i
< 4; i
++){
100 uint16_t val
= src
[x
+ i
- j
*p
->linesize
[0]/2];
101 for(k
= 0; k
< 3; k
++){
102 c
->block
[(i
+ j
*4)*3 + k
] =
103 c
->block2
[remap
[i
+ j
*4]*3 + k
] = (val
>> (10-k
*5)) & 0x1F;
109 for(j
= 0; j
< 4; j
++){
110 for(i
= 0; i
< 4*3; i
++){
111 int t
= prevptr
[x
*3 + i
- j
*3*avctx
->width
] - c
->block
[i
+ j
*4*3];
115 bestscore
/= quality
;
117 // try to find optimal value to fill whole 4x4 block
119 avpriv_init_elbg(c
->block
, 3, 16, c
->avg
, 1, 1, c
->output
, &c
->rnd
);
120 avpriv_do_elbg (c
->block
, 3, 16, c
->avg
, 1, 1, c
->output
, &c
->rnd
);
121 if(c
->avg
[0] == 1) // red component = 1 will be written as skip code
123 for(j
= 0; j
< 4; j
++){
124 for(i
= 0; i
< 4; i
++){
125 for(k
= 0; k
< 3; k
++){
126 int t
= c
->avg
[k
] - c
->block
[(i
+j
*4)*3+k
];
133 if(score
< bestscore
){
135 bestmode
= MODE_FILL
;
137 // search for optimal filling of 2-color block
139 avpriv_init_elbg(c
->block
, 3, 16, c
->codebook
, 2, 1, c
->output
, &c
->rnd
);
140 avpriv_do_elbg (c
->block
, 3, 16, c
->codebook
, 2, 1, c
->output
, &c
->rnd
);
141 // last output value should be always 1, swap codebooks if needed
143 for(i
= 0; i
< 3; i
++)
144 FFSWAP(uint8_t, c
->codebook
[i
], c
->codebook
[i
+3]);
145 for(i
= 0; i
< 16; i
++)
148 for(j
= 0; j
< 4; j
++){
149 for(i
= 0; i
< 4; i
++){
150 for(k
= 0; k
< 3; k
++){
151 int t
= c
->codebook
[c
->output
[i
+j
*4]*3 + k
] - c
->block
[i
*3+k
+j
*4*3];
158 if(score
< bestscore
){
160 bestmode
= MODE_2COL
;
162 // search for optimal filling of 2-color 2x2 subblocks
164 for(i
= 0; i
< 4; i
++){
165 avpriv_init_elbg(c
->block2
+ i
*4*3, 3, 4, c
->codebook2
+ i
*2*3, 2, 1, c
->output2
+ i
*4, &c
->rnd
);
166 avpriv_do_elbg (c
->block2
+ i
*4*3, 3, 4, c
->codebook2
+ i
*2*3, 2, 1, c
->output2
+ i
*4, &c
->rnd
);
168 // last value should be always 1, swap codebooks if needed
170 for(i
= 0; i
< 3; i
++)
171 FFSWAP(uint8_t, c
->codebook2
[i
+18], c
->codebook2
[i
+21]);
172 for(i
= 12; i
< 16; i
++)
175 for(j
= 0; j
< 4; j
++){
176 for(i
= 0; i
< 4; i
++){
177 for(k
= 0; k
< 3; k
++){
178 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];
185 if(score
< bestscore
){
187 bestmode
= MODE_8COL
;
190 if(bestmode
== MODE_SKIP
){
194 if((bestmode
!= MODE_SKIP
&& skips
) || skips
== SKIPS_MAX
){
195 bytestream_put_le16(&dst
, skips
| SKIP_PREFIX
);
201 bytestream_put_le16(&dst
, MKRGB555(c
->avg
,0) | 0x8000);
202 for(j
= 0; j
< 4; j
++)
203 for(i
= 0; i
< 4; i
++)
204 for(k
= 0; k
< 3; k
++)
205 prevptr
[x
*3 + i
*3 + k
- j
*3*avctx
->width
] = c
->avg
[k
];
208 for(j
= 0; j
< 4; j
++){
209 for(i
= 0; i
< 4; i
++){
210 flags
|= (c
->output
[i
+ j
*4]^1) << (i
+ j
*4);
211 for(k
= 0; k
< 3; k
++)
212 prevptr
[x
*3 + i
*3 + k
- j
*3*avctx
->width
] = c
->codebook
[c
->output
[i
+ j
*4]*3 + k
];
215 bytestream_put_le16(&dst
, flags
);
216 bytestream_put_le16(&dst
, MKRGB555(c
->codebook
, 0));
217 bytestream_put_le16(&dst
, MKRGB555(c
->codebook
, 3));
220 for(j
= 0; j
< 4; j
++){
221 for(i
= 0; i
< 4; i
++){
222 flags
|= (c
->output2
[remap
[i
+ j
*4]]^1) << (i
+ j
*4);
223 for(k
= 0; k
< 3; k
++)
224 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
];
227 bytestream_put_le16(&dst
, flags
);
228 bytestream_put_le16(&dst
, MKRGB555(c
->codebook2
, 0) | 0x8000);
229 for(i
= 3; i
< 24; i
+= 3)
230 bytestream_put_le16(&dst
, MKRGB555(c
->codebook2
, i
));
234 src
-= p
->linesize
[0] << 1;
235 prevptr
-= avctx
->width
* 3 * 4;
238 bytestream_put_le16(&dst
, skips
| SKIP_PREFIX
);
240 bytestream_put_byte(&dst
, 0);
241 bytestream_put_byte(&dst
, 0);
249 if (keyframe
) pkt
->flags
|= AV_PKT_FLAG_KEY
;
250 pkt
->size
= dst
- buf
;
260 static av_cold
int encode_init(AVCodecContext
*avctx
)
262 Msvideo1EncContext
* const c
= avctx
->priv_data
;
265 if (av_image_check_size(avctx
->width
, avctx
->height
, 0, avctx
) < 0) {
268 if((avctx
->width
&3) || (avctx
->height
&3)){
269 av_log(avctx
, AV_LOG_ERROR
, "width and height must be multiples of 4\n");
273 avctx
->bits_per_coded_sample
= 16;
275 c
->keyint
= avctx
->keyint_min
;
276 av_lfg_init(&c
->rnd
, 1);
286 static av_cold
int encode_end(AVCodecContext
*avctx
)
288 Msvideo1EncContext
* const c
= avctx
->priv_data
;
295 AVCodec ff_msvideo1_encoder
= {
297 .long_name
= NULL_IF_CONFIG_SMALL("Microsoft Video-1"),
298 .type
= AVMEDIA_TYPE_VIDEO
,
299 .id
= AV_CODEC_ID_MSVIDEO1
,
300 .priv_data_size
= sizeof(Msvideo1EncContext
),
302 .encode2
= encode_frame
,
304 .pix_fmts
= (const enum AVPixelFormat
[]){AV_PIX_FMT_RGB555
, AV_PIX_FMT_NONE
},