FFmpeg
msvideo1enc.c
Go to the documentation of this file.
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 "internal.h"
29 #include "bytestream.h"
30 #include "libavutil/lfg.h"
31 #include "elbg.h"
32 #include "libavutil/imgutils.h"
33 /**
34  * Encoder context
35  */
36 typedef struct Msvideo1EncContext {
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;
51 
52 enum MSV1Mode{
53  MODE_SKIP = 0,
57 };
58 
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]))
62 
63 static const int remap[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 };
64 
66  const AVFrame *pict, int *got_packet)
67 {
68  Msvideo1EncContext * const c = avctx->priv_data;
69  const AVFrame *p = pict;
70  uint16_t *src;
71  uint8_t *prevptr;
72  uint8_t *dst, *buf;
73  int keyframe = 0;
74  int no_skips = 1;
75  int i, j, k, x, y, ret;
76  int skips = 0;
77  int quality = 24;
78 
79  if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*9 + AV_INPUT_BUFFER_MIN_SIZE, 0)) < 0)
80  return ret;
81  dst= buf= pkt->data;
82 
83  if(!c->prev)
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)
88  keyframe = 1;
89 
90 
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;
95  int flags = 0;
96  int score;
97 
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;
104  }
105  }
106  }
107  if(!keyframe){
108  bestscore = 0;
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];
112  bestscore += t*t;
113  }
114  }
115  bestscore /= quality;
116  }
117  // try to find optimal value to fill whole 4x4 block
118  score = 0;
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
122  c->avg[0] = 0;
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];
127  score += t*t;
128  }
129  }
130  }
131  score /= quality;
132  score += 2;
133  if(score < bestscore){
134  bestscore = score;
135  bestmode = MODE_FILL;
136  }
137  // search for optimal filling of 2-color block
138  score = 0;
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
142  if(!c->output[15]){
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++)
146  c->output[i] ^= 1;
147  }
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];
152  score += t*t;
153  }
154  }
155  }
156  score /= quality;
157  score += 6;
158  if(score < bestscore){
159  bestscore = score;
160  bestmode = MODE_2COL;
161  }
162  // search for optimal filling of 2-color 2x2 subblocks
163  score = 0;
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);
167  }
168  // last value should be always 1, swap codebooks if needed
169  if(!c->output2[15]){
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++)
173  c->output2[i] ^= 1;
174  }
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];
179  score += t*t;
180  }
181  }
182  }
183  score /= quality;
184  score += 18;
185  if(score < bestscore){
186  bestscore = score;
187  bestmode = MODE_8COL;
188  }
189 
190  if(bestmode == MODE_SKIP){
191  skips++;
192  no_skips = 0;
193  }
194  if((bestmode != MODE_SKIP && skips) || skips == SKIPS_MAX){
195  bytestream_put_le16(&dst, skips | SKIP_PREFIX);
196  skips = 0;
197  }
198 
199  switch(bestmode){
200  case MODE_FILL:
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];
206  break;
207  case MODE_2COL:
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];
213  }
214  }
215  bytestream_put_le16(&dst, flags);
216  bytestream_put_le16(&dst, MKRGB555(c->codebook, 0));
217  bytestream_put_le16(&dst, MKRGB555(c->codebook, 3));
218  break;
219  case MODE_8COL:
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];
225  }
226  }
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));
231  break;
232  }
233  }
234  src -= p->linesize[0] << 1;
235  prevptr -= avctx->width * 3 * 4;
236  }
237  if(skips)
238  bytestream_put_le16(&dst, skips | SKIP_PREFIX);
239  //EOF
240  bytestream_put_byte(&dst, 0);
241  bytestream_put_byte(&dst, 0);
242 
243  if(no_skips)
244  keyframe = 1;
245  if(keyframe)
246  c->keyint = 0;
247  else
248  c->keyint++;
249  if (keyframe) pkt->flags |= AV_PKT_FLAG_KEY;
250  pkt->size = dst - buf;
251  *got_packet = 1;
252 
253  return 0;
254 }
255 
256 
257 /**
258  * init encoder
259  */
261 {
262  Msvideo1EncContext * const c = avctx->priv_data;
263 
264  c->avctx = avctx;
265  if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
266  return -1;
267  }
268  if((avctx->width&3) || (avctx->height&3)){
269  av_log(avctx, AV_LOG_ERROR, "width and height must be multiples of 4\n");
270  return -1;
271  }
272 
273  avctx->bits_per_coded_sample = 16;
274 
275  c->keyint = avctx->keyint_min;
276  av_lfg_init(&c->rnd, 1);
277 
278  return 0;
279 }
280 
281 
282 
283 /**
284  * Uninit encoder
285  */
287 {
288  Msvideo1EncContext * const c = avctx->priv_data;
289 
290  av_freep(&c->prev);
291 
292  return 0;
293 }
294 
296  .name = "msvideo1",
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),
301  .init = encode_init,
302  .encode2 = encode_frame,
303  .close = encode_end,
305 };
static av_cold int encode_init(AVCodecContext *avctx)
init encoder
Definition: msvideo1enc.c:260
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
const char const char void * val
Definition: avisynth_c.h:863
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
misc image utilities
int output2[16 *3]
Definition: msvideo1enc.c:46
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: avcodec.h:1481
static AVPacket pkt
#define src
Definition: vp8dsp.c:254
AVCodec.
Definition: avcodec.h:3492
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
Definition: encode.c:32
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
int avpriv_do_elbg(int *points, int dim, int numpoints, int *codebook, int numCB, int max_steps, int *closest_cb, AVLFG *rand_state)
Implementation of the Enhanced LBG Algorithm Based on the paper "Neural Networks 14:1219-1237" that c...
Definition: elbg.c:371
uint8_t * data
Definition: avcodec.h:1480
int output[16 *3]
Definition: msvideo1enc.c:45
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:2792
#define AV_INPUT_BUFFER_MIN_SIZE
minimum encoding buffer size Used to avoid some checks during header writing.
Definition: avcodec.h:800
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1512
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: msvideo1enc.c:65
#define SKIP_PREFIX
Definition: msvideo1enc.c:59
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
const char * name
Name of the codec implementation.
Definition: avcodec.h:3499
int codebook[8 *3]
Definition: msvideo1enc.c:43
int block2[16 *3]
Definition: msvideo1enc.c:42
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1486
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:282
int width
picture width / height.
Definition: avcodec.h:1741
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about quality
int avpriv_init_elbg(int *points, int dim, int numpoints, int *codebook, int numCB, int max_steps, int *closest_cb, AVLFG *rand_state)
Initialize the **codebook vector for the elbg algorithm.
Definition: elbg.c:337
Libavcodec external API header.
static const int remap[16]
Definition: msvideo1enc.c:63
static av_cold int encode_end(AVCodecContext *avctx)
Uninit encoder.
Definition: msvideo1enc.c:286
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
int codebook2[8 *3]
Definition: msvideo1enc.c:44
main external API structure.
Definition: avcodec.h:1568
void * buf
Definition: avisynth_c.h:766
MSV1Mode
Definition: msvideo1enc.c:52
AVCodec ff_msvideo1_encoder
Definition: msvideo1enc.c:295
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
#define SKIPS_MAX
Definition: msvideo1enc.c:60
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
#define flags(name, subs,...)
Definition: cbs_av1.c:561
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
int block[16 *3]
Definition: msvideo1enc.c:41
common internal api header.
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:375
void * priv_data
Definition: avcodec.h:1595
AVCodecContext * avctx
Definition: msvideo1enc.c:37
Encoder context.
Definition: msvideo1enc.c:36
#define MKRGB555(in, off)
Definition: msvideo1enc.c:61
#define av_freep(p)
#define FFSWAP(type, a, b)
Definition: common.h:99
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
This structure stores compressed data.
Definition: avcodec.h:1457
int keyint_min
minimum GOP size
Definition: avcodec.h:2149