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 "codec_internal.h"
29 #include "encode.h"
30 #include "bytestream.h"
31 #include "libavutil/lfg.h"
32 #include "libavutil/mem.h"
33 #include "elbg.h"
34 #include "libavutil/imgutils.h"
35 /**
36  * Encoder context
37  */
38 typedef struct Msvideo1EncContext {
40  struct ELBGContext *elbg;
42  uint8_t *prev;
43 
44  int block[16*3];
45  int block2[16*3];
46  int codebook[8*3];
47  int codebook2[8*3];
48  int output[16*3];
49  int output2[16*3];
50  int avg[3];
51  int bestpos;
52  int keyint;
54 
55 enum MSV1Mode{
56  MODE_SKIP = 0,
60 };
61 
62 #define SKIP_PREFIX 0x8400
63 #define SKIPS_MAX 0x03FF
64 #define MKRGB555(in, off) (((in)[off] << 10) | ((in)[(off) + 1] << 5) | ((in)[(off) + 2]))
65 
66 static const int remap[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 };
67 
69  const AVFrame *pict, int *got_packet)
70 {
71  Msvideo1EncContext * const c = avctx->priv_data;
72  const AVFrame *p = pict;
73  const uint16_t *src;
74  uint8_t *prevptr;
75  uint8_t *dst, *buf;
76  int keyframe = 0;
77  int no_skips = 1;
78  int i, j, k, x, y, ret;
79  int skips = 0;
80  int quality = 24;
81 
82  if ((ret = ff_alloc_packet(avctx, pkt, avctx->width*avctx->height*9 + FF_INPUT_BUFFER_MIN_SIZE)) < 0)
83  return ret;
84  dst= buf= pkt->data;
85 
86  if(!c->prev)
87  c->prev = av_malloc(avctx->width * 3 * (avctx->height + 3));
88  if (!c->prev)
89  return AVERROR(ENOMEM);
90  prevptr = c->prev + avctx->width * 3 * (FFALIGN(avctx->height, 4) - 1);
91  src = (const uint16_t*)(p->data[0] + p->linesize[0]*(FFALIGN(avctx->height, 4) - 1));
92  if(c->keyint >= avctx->keyint_min)
93  keyframe = 1;
94 
95 
96  for(y = 0; y < avctx->height; y += 4){
97  for(x = 0; x < avctx->width; x += 4){
98  int bestmode = MODE_SKIP;
99  int bestscore = INT_MAX;
100  int flags = 0;
101  int score;
102 
103  for(j = 0; j < 4; j++){
104  for(i = 0; i < 4; i++){
105  uint16_t val = src[x + i - j*p->linesize[0]/2];
106  for(k = 0; k < 3; k++){
107  c->block[(i + j*4)*3 + k] =
108  c->block2[remap[i + j*4]*3 + k] = (val >> (10-k*5)) & 0x1F;
109  }
110  }
111  }
112  if(!keyframe){
113  bestscore = 0;
114  for(j = 0; j < 4; j++){
115  for(i = 0; i < 4*3; i++){
116  int t = prevptr[x*3 + i - j*3*avctx->width] - c->block[i + j*4*3];
117  bestscore += t*t;
118  }
119  }
120  bestscore /= quality;
121  }
122  // try to find optimal value to fill whole 4x4 block
123  score = 0;
124  ret = avpriv_elbg_do(&c->elbg, c->block, 3, 16, c->avg,
125  1, 1, c->output, &c->rnd, 0);
126  if (ret < 0)
127  return ret;
128  if(c->avg[0] == 1) // red component = 1 will be written as skip code
129  c->avg[0] = 0;
130  for(j = 0; j < 4; j++){
131  for(i = 0; i < 4; i++){
132  for(k = 0; k < 3; k++){
133  int t = c->avg[k] - c->block[(i+j*4)*3+k];
134  score += t*t;
135  }
136  }
137  }
138  score /= quality;
139  score += 2;
140  if(score < bestscore){
141  bestscore = score;
142  bestmode = MODE_FILL;
143  }
144  // search for optimal filling of 2-color block
145  score = 0;
146  ret = avpriv_elbg_do(&c->elbg, c->block, 3, 16, c->codebook,
147  2, 1, c->output, &c->rnd, 0);
148  if (ret < 0)
149  return ret;
150  // last output value should be always 1, swap codebooks if needed
151  if(!c->output[15]){
152  for(i = 0; i < 3; i++)
153  FFSWAP(uint8_t, c->codebook[i], c->codebook[i+3]);
154  for(i = 0; i < 16; i++)
155  c->output[i] ^= 1;
156  }
157  for(j = 0; j < 4; j++){
158  for(i = 0; i < 4; i++){
159  for(k = 0; k < 3; k++){
160  int t = c->codebook[c->output[i+j*4]*3 + k] - c->block[i*3+k+j*4*3];
161  score += t*t;
162  }
163  }
164  }
165  score /= quality;
166  score += 6;
167  if(score < bestscore){
168  bestscore = score;
169  bestmode = MODE_2COL;
170  }
171  // search for optimal filling of 2-color 2x2 subblocks
172  score = 0;
173  for(i = 0; i < 4; i++){
174  ret = avpriv_elbg_do(&c->elbg, c->block2 + i * 4 * 3, 3, 4,
175  c->codebook2 + i * 2 * 3, 2, 1,
176  c->output2 + i * 4, &c->rnd, 0);
177  if (ret < 0)
178  return ret;
179  }
180  // last value should be always 1, swap codebooks if needed
181  if(!c->output2[15]){
182  for(i = 0; i < 3; i++)
183  FFSWAP(uint8_t, c->codebook2[i+18], c->codebook2[i+21]);
184  for(i = 12; i < 16; i++)
185  c->output2[i] ^= 1;
186  }
187  for(j = 0; j < 4; j++){
188  for(i = 0; i < 4; i++){
189  for(k = 0; k < 3; k++){
190  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];
191  score += t*t;
192  }
193  }
194  }
195  score /= quality;
196  score += 18;
197  if(score < bestscore){
198  bestscore = score;
199  bestmode = MODE_8COL;
200  }
201 
202  if(bestmode == MODE_SKIP){
203  skips++;
204  no_skips = 0;
205  }
206  if((bestmode != MODE_SKIP && skips) || skips == SKIPS_MAX){
207  bytestream_put_le16(&dst, skips | SKIP_PREFIX);
208  skips = 0;
209  }
210 
211  switch(bestmode){
212  case MODE_FILL:
213  bytestream_put_le16(&dst, MKRGB555(c->avg,0) | 0x8000);
214  for(j = 0; j < 4; j++)
215  for(i = 0; i < 4; i++)
216  for(k = 0; k < 3; k++)
217  prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->avg[k];
218  break;
219  case MODE_2COL:
220  for(j = 0; j < 4; j++){
221  for(i = 0; i < 4; i++){
222  flags |= (c->output[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->codebook[c->output[i + j*4]*3 + k];
225  }
226  }
227  bytestream_put_le16(&dst, flags);
228  bytestream_put_le16(&dst, MKRGB555(c->codebook, 0));
229  bytestream_put_le16(&dst, MKRGB555(c->codebook, 3));
230  break;
231  case MODE_8COL:
232  for(j = 0; j < 4; j++){
233  for(i = 0; i < 4; i++){
234  flags |= (c->output2[remap[i + j*4]]^1) << (i + j*4);
235  for(k = 0; k < 3; k++)
236  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];
237  }
238  }
239  bytestream_put_le16(&dst, flags);
240  bytestream_put_le16(&dst, MKRGB555(c->codebook2, 0) | 0x8000);
241  for(i = 3; i < 24; i += 3)
242  bytestream_put_le16(&dst, MKRGB555(c->codebook2, i));
243  break;
244  }
245  }
246  src -= p->linesize[0] << 1;
247  prevptr -= avctx->width * 3 * 4;
248  }
249  if(skips)
250  bytestream_put_le16(&dst, skips | SKIP_PREFIX);
251  //EOF
252  bytestream_put_byte(&dst, 0);
253  bytestream_put_byte(&dst, 0);
254 
255  if(no_skips)
256  keyframe = 1;
257  if(keyframe)
258  c->keyint = 0;
259  else
260  c->keyint++;
261  if (keyframe) pkt->flags |= AV_PKT_FLAG_KEY;
262  pkt->size = dst - buf;
263  *got_packet = 1;
264 
265  return 0;
266 }
267 
268 
269 /**
270  * init encoder
271  */
273 {
274  Msvideo1EncContext * const c = avctx->priv_data;
275 
276  c->avctx = avctx;
277  if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
278  return -1;
279  }
280  if((avctx->width&3) || (avctx->height&3)){
281  av_log(avctx, AV_LOG_ERROR, "width and height must be multiples of 4\n");
282  return -1;
283  }
284 
285  avctx->bits_per_coded_sample = 16;
286 
287  c->keyint = avctx->keyint_min;
288  av_lfg_init(&c->rnd, 1);
289 
290  return 0;
291 }
292 
293 
294 
295 /**
296  * Uninit encoder
297  */
299 {
300  Msvideo1EncContext * const c = avctx->priv_data;
301 
302  av_freep(&c->prev);
303  avpriv_elbg_free(&c->elbg);
304 
305  return 0;
306 }
307 
309  .p.name = "msvideo1",
310  CODEC_LONG_NAME("Microsoft Video-1"),
311  .p.type = AVMEDIA_TYPE_VIDEO,
312  .p.id = AV_CODEC_ID_MSVIDEO1,
313  .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
314  .priv_data_size = sizeof(Msvideo1EncContext),
315  .init = encode_init,
317  .close = encode_end,
318  .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB555, AV_PIX_FMT_NONE},
319 };
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
AVCodecContext::keyint_min
int keyint_min
minimum GOP size
Definition: avcodec.h:1024
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
MSV1Mode
MSV1Mode
Definition: msvideo1enc.c:55
av_lfg_init
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
Msvideo1EncContext::codebook2
int codebook2[8 *3]
Definition: msvideo1enc.c:47
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
AVPacket::data
uint8_t * data
Definition: packet.h:524
encode.h
Msvideo1EncContext::avg
int avg[3]
Definition: msvideo1enc.c:50
Msvideo1EncContext::block2
int block2[16 *3]
Definition: msvideo1enc.c:45
FFCodec
Definition: codec_internal.h:126
ff_msvideo1_encoder
const FFCodec ff_msvideo1_encoder
Definition: msvideo1enc.c:308
MODE_FILL
@ MODE_FILL
Definition: msvideo1enc.c:57
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:579
FF_INPUT_BUFFER_MIN_SIZE
#define FF_INPUT_BUFFER_MIN_SIZE
Used by some encoders as upper bound for the length of headers.
Definition: encode.h:33
quality
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about quality
Definition: rate_distortion.txt:12
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:395
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
Msvideo1EncContext::rnd
AVLFG rnd
Definition: msvideo1enc.c:41
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:130
val
static double val(void *priv, double ch)
Definition: aeval.c:78
Msvideo1EncContext::block
int block[16 *3]
Definition: msvideo1enc.c:44
FF_CODEC_ENCODE_CB
#define FF_CODEC_ENCODE_CB(func)
Definition: codec_internal.h:295
avpriv_elbg_do
int avpriv_elbg_do(ELBGContext **elbgp, int *points, int dim, int numpoints, int *codebook, int num_cb, int max_steps, int *closest_cb, AVLFG *rand_state, uintptr_t flags)
Implementation of the Enhanced LBG Algorithm Based on the paper "Neural Networks 14:1219-1237" that c...
Definition: elbg.c:463
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
Msvideo1EncContext::avctx
AVCodecContext * avctx
Definition: msvideo1enc.c:39
lfg.h
SKIP_PREFIX
#define SKIP_PREFIX
Definition: msvideo1enc.c:62
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition: codec.h:159
Msvideo1EncContext::output2
int output2[16 *3]
Definition: msvideo1enc.c:49
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:271
elbg.h
Msvideo1EncContext::prev
uint8_t * prev
Definition: msvideo1enc.c:42
Msvideo1EncContext::bestpos
int bestpos
Definition: msvideo1enc.c:51
c
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
AVLFG
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
AVPacket::size
int size
Definition: packet.h:525
codec_internal.h
MODE_SKIP
@ MODE_SKIP
Definition: msvideo1enc.c:56
avpriv_elbg_free
av_cold void avpriv_elbg_free(ELBGContext **elbgp)
Free an ELBGContext and reset the pointer to it.
Definition: elbg.c:516
remap
static const int remap[16]
Definition: msvideo1enc.c:66
MODE_2COL
@ MODE_2COL
Definition: msvideo1enc.c:58
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:530
encode_end
static av_cold int encode_end(AVCodecContext *avctx)
Uninit encoder.
Definition: msvideo1enc.c:298
AVCodecContext::bits_per_coded_sample
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition: avcodec.h:1567
MODE_8COL
@ MODE_8COL
Definition: msvideo1enc.c:59
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ELBGContext
ELBG internal data.
Definition: elbg.c:47
Msvideo1EncContext
Encoder context.
Definition: msvideo1enc.c:38
AV_PIX_FMT_RGB555
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:466
Msvideo1EncContext::output
int output[16 *3]
Definition: msvideo1enc.c:48
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
AVCodecContext::height
int height
Definition: avcodec.h:618
Msvideo1EncContext::codebook
int codebook[8 *3]
Definition: msvideo1enc.c:46
avcodec.h
ret
ret
Definition: filter_design.txt:187
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
encode_init
static av_cold int encode_init(AVCodecContext *avctx)
init encoder
Definition: msvideo1enc.c:272
AVCodecContext
main external API structure.
Definition: avcodec.h:445
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
Msvideo1EncContext::elbg
struct ELBGContext * elbg
Definition: msvideo1enc.c:40
encode_frame
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: msvideo1enc.c:68
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
MKRGB555
#define MKRGB555(in, off)
Definition: msvideo1enc.c:64
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
AVPacket
This structure stores compressed data.
Definition: packet.h:501
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
bytestream.h
imgutils.h
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:419
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
Msvideo1EncContext::keyint
int keyint
Definition: msvideo1enc.c:52
av_image_check_size
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:318
AV_CODEC_ID_MSVIDEO1
@ AV_CODEC_ID_MSVIDEO1
Definition: codec_id.h:98
ff_alloc_packet
int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and allocate data.
Definition: encode.c:62
SKIPS_MAX
#define SKIPS_MAX
Definition: msvideo1enc.c:63