FFmpeg
Loading...
Searching...
No Matches
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 */
38typedef struct Msvideo1EncContext {
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];
52 int keyint;
54
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
66static 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,
314 .priv_data_size = sizeof(Msvideo1EncContext),
315 .init = encode_init,
317 .close = encode_end,
319};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static double val(void *priv, double ch)
Definition aeval.c:77
const FFCodec ff_msvideo1_encoder
static av_cold int encode_init(AVCodecContext *avctx)
Definition asvenc.c:373
Libavcodec external API header.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define CODEC_PIXFMTS(...)
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
static AVPacket * pkt
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
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
av_cold void avpriv_elbg_free(ELBGContext **elbgp)
Free an ELBGContext and reset the pointer to it.
Definition elbg.c:516
int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and allocate data.
Definition encode.c:62
#define FF_INPUT_BUFFER_MIN_SIZE
Used by some encoders as upper bound for the length of headers.
Definition encode.h:34
static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame, AVPacket *pkt)
Definition ffmpeg_enc.c:694
#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:147
@ AV_CODEC_ID_MSVIDEO1
Definition codec_id.h:96
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
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
@ MODE_SKIP
Definition hevcdec.h:108
static av_cold int encode_end(AVCodecContext *avctx)
Definition huffyuvenc.c:978
misc image utilities
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition lfg.c:32
#define av_cold
Definition attributes.h:117
#define FFSWAP(type, a, b)
Definition macros.h:52
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
static const int remap[16]
Definition msvideo1enc.c:66
static av_cold int encode_init(AVCodecContext *avctx)
init encoder
#define MKRGB555(in, off)
Definition msvideo1enc.c:64
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition msvideo1enc.c:68
MSV1Mode
Definition msvideo1enc.c:55
@ MODE_8COL
Definition msvideo1enc.c:59
@ MODE_FILL
Definition msvideo1enc.c:57
@ MODE_2COL
Definition msvideo1enc.c:58
static av_cold int encode_end(AVCodecContext *avctx)
Uninit encoder.
#define SKIPS_MAX
Definition msvideo1enc.c:63
#define SKIP_PREFIX
Definition msvideo1enc.c:62
#define av_malloc(s)
Definition ops_static.c:52
#define AV_PIX_FMT_RGB555
Definition pixfmt.h:533
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
int keyint_min
minimum GOP size
Definition avcodec.h:1014
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition avcodec.h:1564
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
Context structure for the Lagged Fibonacci PRNG.
Definition lfg.h:33
This structure stores compressed data.
Definition packet.h:580
ELBG internal data.
Definition elbg.c:47
Encoder context.
Definition msvideo1enc.c:38
struct ELBGContext * elbg
Definition msvideo1enc.c:40
int block2[16 *3]
Definition msvideo1enc.c:45
AVCodecContext * avctx
Definition msvideo1enc.c:39
int output[16 *3]
Definition msvideo1enc.c:48
int codebook2[8 *3]
Definition msvideo1enc.c:47
int output2[16 *3]
Definition msvideo1enc.c:49
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static const uint8_t quality[]
Definition vmixdec.c:58
static double c[64]