2 * Cinepak encoder (c) 2011 Tomas Härdin
3 * http://titan.codemill.se/~tomhar/cinepakenc.patch
5 * Fixes and improvements, vintage decoders compatibility
6 * (c) 2013, 2014 Rl, Aetey Global Technologies AB
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
29 * - optimize: color space conversion (move conversion to libswscale), ...
31 * - "optimally" split the frame into several non-regular areas
32 * using a separate codebook pair for each area and approximating
33 * the area by several rectangular strips (generally not full width ones)
34 * (use quadtree splitting? a simple fixed-granularity grid?)
39 #include "libavutil/avassert.h"
40 #include "libavutil/common.h"
41 #include "libavutil/internal.h"
42 #include "libavutil/intreadwrite.h"
43 #include "libavutil/lfg.h"
44 #include "libavutil/opt.h"
50 #define CVID_HEADER_SIZE 10
51 #define STRIP_HEADER_SIZE 12
52 #define CHUNK_HEADER_SIZE 4
54 #define MB_SIZE 4 //4x4 MBs
55 #define MB_AREA (MB_SIZE * MB_SIZE)
57 #define VECTOR_MAX 6 // six or four entries per vector depending on format
58 #define CODEBOOK_MAX 256 // size of a codebook
60 #define MAX_STRIPS 32 // Note: having fewer choices regarding the number of strips speeds up encoding (obviously)
61 #define MIN_STRIPS 1 // Note: having more strips speeds up encoding the frame (this is less obvious)
62 // MAX_STRIPS limits the maximum quality you can reach
63 // when you want high quality on high resolutions,
64 // MIN_STRIPS limits the minimum efficiently encodable bit rate
66 // the numbers are only used for brute force optimization for the first frame,
67 // for the following frames they are adaptively readjusted
68 // NOTE the decoder in ffmpeg has its own arbitrary limitation on the number
69 // of strips, currently 32
71 typedef enum CinepakMode
{
79 typedef enum mb_encoding
{
87 typedef struct mb_info
{
88 int v1_vector
; // index into v1 codebook
89 int v1_error
; // error when using V1 encoding
90 int v4_vector
[4]; // indices into v4 codebook
91 int v4_error
; // error when using V4 encoding
92 int skip_error
; // error when block is skipped (aka copied from last frame)
93 mb_encoding best_encoding
; // last result from calculate_mode_score()
96 typedef struct strip_info
{
97 int v1_codebook
[CODEBOOK_MAX
* VECTOR_MAX
];
98 int v4_codebook
[CODEBOOK_MAX
* VECTOR_MAX
];
104 typedef struct CinepakEncContext
{
105 AVCodecContext
*avctx
;
106 unsigned char *pict_bufs
[4], *strip_buf
, *frame_buf
;
109 AVFrame
*scratch_frame
;
110 AVFrame
*input_frame
;
111 enum AVPixelFormat pix_fmt
;
114 int curframe
, keyint
;
118 int *codebook_closest
;
119 mb_info
*mb
; // MB RD state
120 int min_strips
; // the current limit
121 int max_strips
; // the current limit
123 int max_extra_cb_iterations
;
127 int strip_number_delta_range
;
130 #define OFFSET(x) offsetof(CinepakEncContext, x)
131 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
132 static const AVOption options
[] = {
133 { "max_extra_cb_iterations", "Max extra codebook recalculation passes, more is better and slower",
134 OFFSET(max_extra_cb_iterations
), AV_OPT_TYPE_INT
, { .i64
= 2 }, 0, INT_MAX
, VE
},
135 { "skip_empty_cb", "Avoid wasting bytes, ignore vintage MacOS decoder",
136 OFFSET(skip_empty_cb
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, 1, VE
},
137 { "max_strips", "Limit strips/frame, vintage compatible is 1..3, otherwise the more the better",
138 OFFSET(max_max_strips
), AV_OPT_TYPE_INT
, { .i64
= 3 }, MIN_STRIPS
, MAX_STRIPS
, VE
},
139 { "min_strips", "Enforce min strips/frame, more is worse and faster, must be <= max_strips",
140 OFFSET(min_min_strips
), AV_OPT_TYPE_INT
, { .i64
= MIN_STRIPS
}, MIN_STRIPS
, MAX_STRIPS
, VE
},
141 { "strip_number_adaptivity", "How fast the strip number adapts, more is slightly better, much slower",
142 OFFSET(strip_number_delta_range
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, MAX_STRIPS
- MIN_STRIPS
, VE
},
146 static const AVClass cinepak_class
= {
147 .class_name
= "cinepak",
148 .item_name
= av_default_item_name
,
150 .version
= LIBAVUTIL_VERSION_INT
,
153 static av_cold
int cinepak_encode_init(AVCodecContext
*avctx
)
155 CinepakEncContext
*s
= avctx
->priv_data
;
156 int x
, mb_count
, strip_buf_size
, frame_buf_size
;
158 if (avctx
->width
& 3 || avctx
->height
& 3) {
159 av_log(avctx
, AV_LOG_ERROR
, "width and height must be multiples of four (got %ix%i)\n",
160 avctx
->width
, avctx
->height
);
161 return AVERROR(EINVAL
);
164 if (s
->min_min_strips
> s
->max_max_strips
) {
165 av_log(avctx
, AV_LOG_ERROR
, "minimum number of strips must not exceed maximum (got %i and %i)\n",
166 s
->min_min_strips
, s
->max_max_strips
);
167 return AVERROR(EINVAL
);
170 if (!(s
->last_frame
= av_frame_alloc()))
171 return AVERROR(ENOMEM
);
172 if (!(s
->best_frame
= av_frame_alloc()))
174 if (!(s
->scratch_frame
= av_frame_alloc()))
176 if (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
)
177 if (!(s
->input_frame
= av_frame_alloc()))
180 if (!(s
->codebook_input
= av_malloc_array((avctx
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4) * (avctx
->width
* avctx
->height
) >> 2, sizeof(*s
->codebook_input
))))
183 if (!(s
->codebook_closest
= av_malloc_array((avctx
->width
* avctx
->height
) >> 2, sizeof(*s
->codebook_closest
))))
186 for (x
= 0; x
< (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
? 4 : 3); x
++)
187 if (!(s
->pict_bufs
[x
] = av_malloc((avctx
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4) * (avctx
->width
* avctx
->height
) >> 2)))
190 mb_count
= avctx
->width
* avctx
->height
/ MB_AREA
;
192 // the largest possible chunk is 0x31 with all MBs encoded in V4 mode
193 // and full codebooks being replaced in INTER mode,
194 // which is 34 bits per MB
195 // and 2*256 extra flag bits per strip
196 strip_buf_size
= STRIP_HEADER_SIZE
+ 3 * CHUNK_HEADER_SIZE
+ 2 * VECTOR_MAX
* CODEBOOK_MAX
+ 4 * (mb_count
+ (mb_count
+ 15) / 16) + (2 * CODEBOOK_MAX
) / 8;
198 frame_buf_size
= CVID_HEADER_SIZE
+ s
->max_max_strips
* strip_buf_size
;
200 if (!(s
->strip_buf
= av_malloc(strip_buf_size
)))
203 if (!(s
->frame_buf
= av_malloc(frame_buf_size
)))
206 if (!(s
->mb
= av_malloc_array(mb_count
, sizeof(mb_info
))))
209 av_lfg_init(&s
->randctx
, 1);
212 s
->h
= avctx
->height
;
213 s
->frame_buf_size
= frame_buf_size
;
215 s
->keyint
= avctx
->keyint_min
;
216 s
->pix_fmt
= avctx
->pix_fmt
;
219 s
->last_frame
->data
[0] = s
->pict_bufs
[0];
220 s
->last_frame
->linesize
[0] = s
->w
;
221 s
->best_frame
->data
[0] = s
->pict_bufs
[1];
222 s
->best_frame
->linesize
[0] = s
->w
;
223 s
->scratch_frame
->data
[0] = s
->pict_bufs
[2];
224 s
->scratch_frame
->linesize
[0] = s
->w
;
226 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
227 s
->last_frame
->data
[1] = s
->last_frame
->data
[0] + s
->w
* s
->h
;
228 s
->last_frame
->data
[2] = s
->last_frame
->data
[1] + ((s
->w
* s
->h
) >> 2);
229 s
->last_frame
->linesize
[1] =
230 s
->last_frame
->linesize
[2] = s
->w
>> 1;
232 s
->best_frame
->data
[1] = s
->best_frame
->data
[0] + s
->w
* s
->h
;
233 s
->best_frame
->data
[2] = s
->best_frame
->data
[1] + ((s
->w
* s
->h
) >> 2);
234 s
->best_frame
->linesize
[1] =
235 s
->best_frame
->linesize
[2] = s
->w
>> 1;
237 s
->scratch_frame
->data
[1] = s
->scratch_frame
->data
[0] + s
->w
* s
->h
;
238 s
->scratch_frame
->data
[2] = s
->scratch_frame
->data
[1] + ((s
->w
* s
->h
) >> 2);
239 s
->scratch_frame
->linesize
[1] =
240 s
->scratch_frame
->linesize
[2] = s
->w
>> 1;
242 s
->input_frame
->data
[0] = s
->pict_bufs
[3];
243 s
->input_frame
->linesize
[0] = s
->w
;
244 s
->input_frame
->data
[1] = s
->input_frame
->data
[0] + s
->w
* s
->h
;
245 s
->input_frame
->data
[2] = s
->input_frame
->data
[1] + ((s
->w
* s
->h
) >> 2);
246 s
->input_frame
->linesize
[1] =
247 s
->input_frame
->linesize
[2] = s
->w
>> 1;
250 s
->min_strips
= s
->min_min_strips
;
251 s
->max_strips
= s
->max_max_strips
;
256 av_frame_free(&s
->last_frame
);
257 av_frame_free(&s
->best_frame
);
258 av_frame_free(&s
->scratch_frame
);
259 if (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
)
260 av_frame_free(&s
->input_frame
);
261 av_freep(&s
->codebook_input
);
262 av_freep(&s
->codebook_closest
);
263 av_freep(&s
->strip_buf
);
264 av_freep(&s
->frame_buf
);
267 for (x
= 0; x
< (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
? 4 : 3); x
++)
268 av_freep(&s
->pict_bufs
[x
]);
270 return AVERROR(ENOMEM
);
273 static int64_t calculate_mode_score(CinepakEncContext
*s
, int h
,
274 strip_info
*info
, int report
,
275 int *training_set_v1_shrunk
,
276 int *training_set_v4_shrunk
)
278 // score = FF_LAMBDA_SCALE * error + lambda * bits
280 int entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
281 int mb_count
= s
->w
* h
/ MB_AREA
;
283 int64_t score1
, score2
, score3
;
284 int64_t ret
= s
->lambda
* ((info
->v1_size
? CHUNK_HEADER_SIZE
+ info
->v1_size
* entry_size
: 0) +
285 (info
->v4_size
? CHUNK_HEADER_SIZE
+ info
->v4_size
* entry_size
: 0) +
286 CHUNK_HEADER_SIZE
) << 3;
288 switch (info
->mode
) {
291 ret
+= s
->lambda
* 8 * mb_count
;
293 // while calculating we assume all blocks are ENC_V1
294 for (x
= 0; x
< mb_count
; x
++) {
296 ret
+= FF_LAMBDA_SCALE
* mb
->v1_error
;
297 // this function is never called for report in MODE_V1_ONLY
299 mb
->best_encoding
= ENC_V1
;
304 // 9 or 33 bits per MB
306 // no moves between the corresponding training sets are allowed
307 *training_set_v1_shrunk
= *training_set_v4_shrunk
= 0;
308 for (x
= 0; x
< mb_count
; x
++) {
311 if (mb
->best_encoding
== ENC_V1
)
312 score1
= s
->lambda
* 9 + FF_LAMBDA_SCALE
* (mberr
= mb
->v1_error
);
314 score1
= s
->lambda
* 33 + FF_LAMBDA_SCALE
* (mberr
= mb
->v4_error
);
317 } else { // find best mode per block
318 for (x
= 0; x
< mb_count
; x
++) {
320 score1
= s
->lambda
* 9 + FF_LAMBDA_SCALE
* mb
->v1_error
;
321 score2
= s
->lambda
* 33 + FF_LAMBDA_SCALE
* mb
->v4_error
;
323 if (score1
<= score2
) {
325 mb
->best_encoding
= ENC_V1
;
328 mb
->best_encoding
= ENC_V4
;
335 // 1, 10 or 34 bits per MB
337 int v1_shrunk
= 0, v4_shrunk
= 0;
338 for (x
= 0; x
< mb_count
; x
++) {
340 // it is OK to move blocks to ENC_SKIP here
341 // but not to any codebook encoding!
342 score1
= s
->lambda
* 1 + FF_LAMBDA_SCALE
* mb
->skip_error
;
343 if (mb
->best_encoding
== ENC_SKIP
) {
345 } else if (mb
->best_encoding
== ENC_V1
) {
346 if ((score2
= s
->lambda
* 10 + FF_LAMBDA_SCALE
* mb
->v1_error
) >= score1
) {
347 mb
->best_encoding
= ENC_SKIP
;
354 if ((score3
= s
->lambda
* 34 + FF_LAMBDA_SCALE
* mb
->v4_error
) >= score1
) {
355 mb
->best_encoding
= ENC_SKIP
;
363 *training_set_v1_shrunk
= v1_shrunk
;
364 *training_set_v4_shrunk
= v4_shrunk
;
365 } else { // find best mode per block
366 for (x
= 0; x
< mb_count
; x
++) {
368 score1
= s
->lambda
* 1 + FF_LAMBDA_SCALE
* mb
->skip_error
;
369 score2
= s
->lambda
* 10 + FF_LAMBDA_SCALE
* mb
->v1_error
;
370 score3
= s
->lambda
* 34 + FF_LAMBDA_SCALE
* mb
->v4_error
;
372 if (score1
<= score2
&& score1
<= score3
) {
374 mb
->best_encoding
= ENC_SKIP
;
375 } else if (score2
<= score3
) {
377 mb
->best_encoding
= ENC_V1
;
380 mb
->best_encoding
= ENC_V4
;
391 static int write_chunk_header(unsigned char *buf
, int chunk_type
, int chunk_size
)
394 AV_WB24(&buf
[1], chunk_size
+ CHUNK_HEADER_SIZE
);
395 return CHUNK_HEADER_SIZE
;
398 static int encode_codebook(CinepakEncContext
*s
, int *codebook
, int size
,
399 int chunk_type_yuv
, int chunk_type_gray
,
402 int x
, y
, ret
, entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
403 int incremental_codebook_replacement_mode
= 0; // hardcoded here,
404 // the compiler should notice that this is a constant -- rl
406 ret
= write_chunk_header(buf
,
407 s
->pix_fmt
== AV_PIX_FMT_RGB24
?
408 chunk_type_yuv
+ (incremental_codebook_replacement_mode
? 1 : 0) :
409 chunk_type_gray
+ (incremental_codebook_replacement_mode
? 1 : 0),
411 (incremental_codebook_replacement_mode
? (size
+ 31) / 32 * 4 : 0));
413 // we do codebook encoding according to the "intra" mode
414 // but we keep the "dead" code for reference in case we will want
415 // to use incremental codebook updates (which actually would give us
416 // "kind of" motion compensation, especially in 1 strip/frame case) -- rl
417 // (of course, the code will be not useful as-is)
418 if (incremental_codebook_replacement_mode
) {
421 for (x
= 0; x
< size
; x
++) {
427 flags
= ((flags
>> 1) | 0x80000000);
428 for (y
= 0; y
< entry_size
; y
++)
429 buf
[ret
++] = codebook
[y
+ x
* entry_size
] ^ (y
>= 4 ? 0x80 : 0);
430 if ((flags
& 0xffffffff) == 0xffffffff) {
431 AV_WB32(&buf
[flagsind
], flags
);
436 AV_WB32(&buf
[flagsind
], flags
);
438 for (x
= 0; x
< size
; x
++)
439 for (y
= 0; y
< entry_size
; y
++)
440 buf
[ret
++] = codebook
[y
+ x
* entry_size
] ^ (y
>= 4 ? 0x80 : 0);
445 // sets out to the sub picture starting at (x,y) in in
446 static void get_sub_picture(CinepakEncContext
*s
, int x
, int y
,
447 uint8_t * in_data
[4], int in_linesize
[4],
448 uint8_t *out_data
[4], int out_linesize
[4])
450 out_data
[0] = in_data
[0] + x
+ y
* in_linesize
[0];
451 out_linesize
[0] = in_linesize
[0];
453 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
454 out_data
[1] = in_data
[1] + (x
>> 1) + (y
>> 1) * in_linesize
[1];
455 out_linesize
[1] = in_linesize
[1];
457 out_data
[2] = in_data
[2] + (x
>> 1) + (y
>> 1) * in_linesize
[2];
458 out_linesize
[2] = in_linesize
[2];
462 // decodes the V1 vector in mb into the 4x4 MB pointed to by data
463 static void decode_v1_vector(CinepakEncContext
*s
, uint8_t *data
[4],
464 int linesize
[4], int v1_vector
, strip_info
*info
)
466 int entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
470 data
[0][ linesize
[0]] =
471 data
[0][1 + linesize
[0]] = info
->v1_codebook
[v1_vector
* entry_size
];
475 data
[0][2 + linesize
[0]] =
476 data
[0][3 + linesize
[0]] = info
->v1_codebook
[v1_vector
* entry_size
+ 1];
478 data
[0][ 2 * linesize
[0]] =
479 data
[0][1 + 2 * linesize
[0]] =
480 data
[0][ 3 * linesize
[0]] =
481 data
[0][1 + 3 * linesize
[0]] = info
->v1_codebook
[v1_vector
* entry_size
+ 2];
483 data
[0][2 + 2 * linesize
[0]] =
484 data
[0][3 + 2 * linesize
[0]] =
485 data
[0][2 + 3 * linesize
[0]] =
486 data
[0][3 + 3 * linesize
[0]] = info
->v1_codebook
[v1_vector
* entry_size
+ 3];
488 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
491 data
[1][ linesize
[1]] =
492 data
[1][1 + linesize
[1]] = info
->v1_codebook
[v1_vector
* entry_size
+ 4];
496 data
[2][ linesize
[2]] =
497 data
[2][1 + linesize
[2]] = info
->v1_codebook
[v1_vector
* entry_size
+ 5];
501 // decodes the V4 vectors in mb into the 4x4 MB pointed to by data
502 static void decode_v4_vector(CinepakEncContext
*s
, uint8_t *data
[4],
503 int linesize
[4], int *v4_vector
, strip_info
*info
)
505 int i
, x
, y
, entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
507 for (i
= y
= 0; y
< 4; y
+= 2) {
508 for (x
= 0; x
< 4; x
+= 2, i
++) {
509 data
[0][x
+ y
* linesize
[0]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
];
510 data
[0][x
+ 1 + y
* linesize
[0]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 1];
511 data
[0][x
+ (y
+ 1) * linesize
[0]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 2];
512 data
[0][x
+ 1 + (y
+ 1) * linesize
[0]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 3];
514 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
515 data
[1][(x
>> 1) + (y
>> 1) * linesize
[1]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 4];
516 data
[2][(x
>> 1) + (y
>> 1) * linesize
[2]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 5];
522 static void copy_mb(CinepakEncContext
*s
,
523 uint8_t *a_data
[4], int a_linesize
[4],
524 uint8_t *b_data
[4], int b_linesize
[4])
528 for (y
= 0; y
< MB_SIZE
; y
++)
529 memcpy(a_data
[0] + y
* a_linesize
[0], b_data
[0] + y
* b_linesize
[0],
532 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
533 for (p
= 1; p
<= 2; p
++)
534 for (y
= 0; y
< MB_SIZE
/ 2; y
++)
535 memcpy(a_data
[p
] + y
* a_linesize
[p
],
536 b_data
[p
] + y
* b_linesize
[p
],
541 static int encode_mode(CinepakEncContext
*s
, int h
,
542 uint8_t *scratch_data
[4], int scratch_linesize
[4],
543 uint8_t *last_data
[4], int last_linesize
[4],
544 strip_info
*info
, unsigned char *buf
)
546 int x
, y
, z
, flags
, bits
, temp_size
, header_ofs
, ret
= 0, mb_count
= s
->w
* h
/ MB_AREA
;
547 int needs_extra_bit
, should_write_temp
;
548 unsigned char temp
[64]; // 32/2 = 16 V4 blocks at 4 B each -> 64 B
550 uint8_t *sub_scratch_data
[4] = { 0 }, *sub_last_data
[4] = { 0 };
551 int sub_scratch_linesize
[4] = { 0 }, sub_last_linesize
[4] = { 0 };
554 ////// MacOS vintage decoder compatibility dictates the presence of
555 ////// the codebook chunk even when the codebook is empty - pretty dumb...
556 ////// and also the certain order of the codebook chunks -- rl
557 if (info
->v4_size
|| !s
->skip_empty_cb
)
558 ret
+= encode_codebook(s
, info
->v4_codebook
, info
->v4_size
, 0x20, 0x24, buf
+ ret
);
560 if (info
->v1_size
|| !s
->skip_empty_cb
)
561 ret
+= encode_codebook(s
, info
->v1_codebook
, info
->v1_size
, 0x22, 0x26, buf
+ ret
);
563 // update scratch picture
564 for (z
= y
= 0; y
< h
; y
+= MB_SIZE
)
565 for (x
= 0; x
< s
->w
; x
+= MB_SIZE
, z
++) {
568 get_sub_picture(s
, x
, y
, scratch_data
, scratch_linesize
,
569 sub_scratch_data
, sub_scratch_linesize
);
571 if (info
->mode
== MODE_MC
&& mb
->best_encoding
== ENC_SKIP
) {
572 get_sub_picture(s
, x
, y
, last_data
, last_linesize
,
573 sub_last_data
, sub_last_linesize
);
574 copy_mb(s
, sub_scratch_data
, sub_scratch_linesize
,
575 sub_last_data
, sub_last_linesize
);
576 } else if (info
->mode
== MODE_V1_ONLY
|| mb
->best_encoding
== ENC_V1
)
577 decode_v1_vector(s
, sub_scratch_data
, sub_scratch_linesize
,
578 mb
->v1_vector
, info
);
580 decode_v4_vector(s
, sub_scratch_data
, sub_scratch_linesize
,
581 mb
->v4_vector
, info
);
584 switch (info
->mode
) {
586 ret
+= write_chunk_header(buf
+ ret
, 0x32, mb_count
);
588 for (x
= 0; x
< mb_count
; x
++)
589 buf
[ret
++] = s
->mb
[x
].v1_vector
;
593 // remember header position
595 ret
+= CHUNK_HEADER_SIZE
;
597 for (x
= 0; x
< mb_count
; x
+= 32) {
599 for (y
= x
; y
< FFMIN(x
+ 32, mb_count
); y
++)
600 if (s
->mb
[y
].best_encoding
== ENC_V4
)
601 flags
|= 1 << (31 - y
+ x
);
603 AV_WB32(&buf
[ret
], flags
);
606 for (y
= x
; y
< FFMIN(x
+ 32, mb_count
); y
++) {
609 if (mb
->best_encoding
== ENC_V1
)
610 buf
[ret
++] = mb
->v1_vector
;
612 for (z
= 0; z
< 4; z
++)
613 buf
[ret
++] = mb
->v4_vector
[z
];
617 write_chunk_header(buf
+ header_ofs
, 0x30, ret
- header_ofs
- CHUNK_HEADER_SIZE
);
621 // remember header position
623 ret
+= CHUNK_HEADER_SIZE
;
624 flags
= bits
= temp_size
= 0;
626 for (x
= 0; x
< mb_count
; x
++) {
628 flags
|= (mb
->best_encoding
!= ENC_SKIP
) << (31 - bits
++);
630 should_write_temp
= 0;
632 if (mb
->best_encoding
!= ENC_SKIP
) {
634 flags
|= (mb
->best_encoding
== ENC_V4
) << (31 - bits
++);
640 AV_WB32(&buf
[ret
], flags
);
644 if (mb
->best_encoding
== ENC_SKIP
|| needs_extra_bit
) {
645 memcpy(&buf
[ret
], temp
, temp_size
);
649 should_write_temp
= 1;
652 if (needs_extra_bit
) {
653 flags
= (mb
->best_encoding
== ENC_V4
) << 31;
657 if (mb
->best_encoding
== ENC_V1
)
658 temp
[temp_size
++] = mb
->v1_vector
;
659 else if (mb
->best_encoding
== ENC_V4
)
660 for (z
= 0; z
< 4; z
++)
661 temp
[temp_size
++] = mb
->v4_vector
[z
];
663 if (should_write_temp
) {
664 memcpy(&buf
[ret
], temp
, temp_size
);
671 AV_WB32(&buf
[ret
], flags
);
673 memcpy(&buf
[ret
], temp
, temp_size
);
677 write_chunk_header(buf
+ header_ofs
, 0x31, ret
- header_ofs
- CHUNK_HEADER_SIZE
);
685 // computes distortion of 4x4 MB in b compared to a
686 static int compute_mb_distortion(CinepakEncContext
*s
,
687 uint8_t *a_data
[4], int a_linesize
[4],
688 uint8_t *b_data
[4], int b_linesize
[4])
690 int x
, y
, p
, d
, ret
= 0;
692 for (y
= 0; y
< MB_SIZE
; y
++)
693 for (x
= 0; x
< MB_SIZE
; x
++) {
694 d
= a_data
[0][x
+ y
* a_linesize
[0]] - b_data
[0][x
+ y
* b_linesize
[0]];
698 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
699 for (p
= 1; p
<= 2; p
++) {
700 for (y
= 0; y
< MB_SIZE
/ 2; y
++)
701 for (x
= 0; x
< MB_SIZE
/ 2; x
++) {
702 d
= a_data
[p
][x
+ y
* a_linesize
[p
]] - b_data
[p
][x
+ y
* b_linesize
[p
]];
711 // return the possibly adjusted size of the codebook
712 #define CERTAIN(x) ((x) != ENC_UNCERTAIN)
713 static int quantize(CinepakEncContext
*s
, int h
, uint8_t *data
[4],
714 int linesize
[4], int v1mode
, strip_info
*info
,
715 mb_encoding encoding
)
717 int x
, y
, i
, j
, k
, x2
, y2
, x3
, y3
, plane
, shift
, mbn
;
718 int entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
719 int *codebook
= v1mode
? info
->v1_codebook
: info
->v4_codebook
;
720 int size
= v1mode
? info
->v1_size
: info
->v4_size
;
721 int64_t total_error
= 0;
722 uint8_t vq_pict_buf
[(MB_AREA
* 3) / 2];
723 uint8_t *sub_data
[4], *vq_data
[4];
724 int sub_linesize
[4], vq_linesize
[4];
726 for (mbn
= i
= y
= 0; y
< h
; y
+= MB_SIZE
) {
727 for (x
= 0; x
< s
->w
; x
+= MB_SIZE
, ++mbn
) {
730 if (CERTAIN(encoding
)) {
731 // use for the training only the blocks known to be to be encoded [sic:-]
732 if (s
->mb
[mbn
].best_encoding
!= encoding
)
736 base
= s
->codebook_input
+ i
* entry_size
;
739 for (j
= y2
= 0; y2
< entry_size
; y2
+= 2)
740 for (x2
= 0; x2
< 4; x2
+= 2, j
++) {
741 plane
= y2
< 4 ? 0 : 1 + (x2
>> 1);
742 shift
= y2
< 4 ? 0 : 1;
745 base
[j
] = (data
[plane
][((x
+ x3
) >> shift
) + ((y
+ y3
) >> shift
) * linesize
[plane
]] +
746 data
[plane
][((x
+ x3
) >> shift
) + 1 + ((y
+ y3
) >> shift
) * linesize
[plane
]] +
747 data
[plane
][((x
+ x3
) >> shift
) + (((y
+ y3
) >> shift
) + 1) * linesize
[plane
]] +
748 data
[plane
][((x
+ x3
) >> shift
) + 1 + (((y
+ y3
) >> shift
) + 1) * linesize
[plane
]]) >> 2;
752 for (j
= y2
= 0; y2
< MB_SIZE
; y2
+= 2) {
753 for (x2
= 0; x2
< MB_SIZE
; x2
+= 2)
754 for (k
= 0; k
< entry_size
; k
++, j
++) {
755 plane
= k
>= 4 ? k
- 3 : 0;
761 x3
= x
+ x2
+ (k
& 1);
762 y3
= y
+ y2
+ (k
>> 1);
765 base
[j
] = data
[plane
][x3
+ y3
* linesize
[plane
]];
773 if (i
== 0) // empty training set, nothing to do
778 ff_init_elbg(s
->codebook_input
, entry_size
, i
, codebook
, size
, 1, s
->codebook_closest
, &s
->randctx
);
779 ff_do_elbg(s
->codebook_input
, entry_size
, i
, codebook
, size
, 1, s
->codebook_closest
, &s
->randctx
);
781 // set up vq_data, which contains a single MB
782 vq_data
[0] = vq_pict_buf
;
783 vq_linesize
[0] = MB_SIZE
;
784 vq_data
[1] = &vq_pict_buf
[MB_AREA
];
785 vq_data
[2] = vq_data
[1] + (MB_AREA
>> 2);
787 vq_linesize
[2] = MB_SIZE
>> 1;
790 for (i
= j
= y
= 0; y
< h
; y
+= MB_SIZE
)
791 for (x
= 0; x
< s
->w
; x
+= MB_SIZE
, j
++) {
792 mb_info
*mb
= &s
->mb
[j
];
793 // skip uninteresting blocks if we know their preferred encoding
794 if (CERTAIN(encoding
) && mb
->best_encoding
!= encoding
)
797 // point sub_data to current MB
798 get_sub_picture(s
, x
, y
, data
, linesize
, sub_data
, sub_linesize
);
801 mb
->v1_vector
= s
->codebook_closest
[i
];
803 // fill in vq_data with V1 data
804 decode_v1_vector(s
, vq_data
, vq_linesize
, mb
->v1_vector
, info
);
806 mb
->v1_error
= compute_mb_distortion(s
, sub_data
, sub_linesize
,
807 vq_data
, vq_linesize
);
808 total_error
+= mb
->v1_error
;
810 for (k
= 0; k
< 4; k
++)
811 mb
->v4_vector
[k
] = s
->codebook_closest
[i
+ k
];
813 // fill in vq_data with V4 data
814 decode_v4_vector(s
, vq_data
, vq_linesize
, mb
->v4_vector
, info
);
816 mb
->v4_error
= compute_mb_distortion(s
, sub_data
, sub_linesize
,
817 vq_data
, vq_linesize
);
818 total_error
+= mb
->v4_error
;
822 // check that we did it right in the beginning of the function
823 av_assert0(i
>= size
); // training set is no smaller than the codebook
828 static void calculate_skip_errors(CinepakEncContext
*s
, int h
,
829 uint8_t *last_data
[4], int last_linesize
[4],
830 uint8_t *data
[4], int linesize
[4],
834 uint8_t *sub_last_data
[4], *sub_pict_data
[4];
835 int sub_last_linesize
[4], sub_pict_linesize
[4];
837 for (i
= y
= 0; y
< h
; y
+= MB_SIZE
)
838 for (x
= 0; x
< s
->w
; x
+= MB_SIZE
, i
++) {
839 get_sub_picture(s
, x
, y
, last_data
, last_linesize
,
840 sub_last_data
, sub_last_linesize
);
841 get_sub_picture(s
, x
, y
, data
, linesize
,
842 sub_pict_data
, sub_pict_linesize
);
844 s
->mb
[i
].skip_error
=
845 compute_mb_distortion(s
,
846 sub_last_data
, sub_last_linesize
,
847 sub_pict_data
, sub_pict_linesize
);
851 static void write_strip_header(CinepakEncContext
*s
, int y
, int h
, int keyframe
,
852 unsigned char *buf
, int strip_size
)
854 // actually we are exclusively using intra strip coding (how much can we win
855 // otherwise? how to choose which part of a codebook to update?),
856 // keyframes are different only because we disallow ENC_SKIP on them -- rl
857 // (besides, the logic here used to be inverted: )
858 // buf[0] = keyframe ? 0x11: 0x10;
859 buf
[0] = keyframe
? 0x10 : 0x11;
860 AV_WB24(&buf
[1], strip_size
+ STRIP_HEADER_SIZE
);
861 // AV_WB16(&buf[4], y); /* using absolute y values works -- rl */
862 AV_WB16(&buf
[4], 0); /* using relative values works as well -- rl */
864 // AV_WB16(&buf[8], y + h); /* using absolute y values works -- rl */
865 AV_WB16(&buf
[8], h
); /* using relative values works as well -- rl */
866 AV_WB16(&buf
[10], s
->w
);
869 static int rd_strip(CinepakEncContext
*s
, int y
, int h
, int keyframe
,
870 uint8_t *last_data
[4], int last_linesize
[4],
871 uint8_t *data
[4], int linesize
[4],
872 uint8_t *scratch_data
[4], int scratch_linesize
[4],
873 unsigned char *buf
, int64_t *best_score
)
878 // for codebook optimization:
879 int v1enough
, v1_size
, v4enough
, v4_size
;
880 int new_v1_size
, new_v4_size
;
881 int v1shrunk
, v4shrunk
;
884 calculate_skip_errors(s
, h
, last_data
, last_linesize
, data
, linesize
,
887 // try some powers of 4 for the size of the codebooks
888 // constraint the v4 codebook to be no bigger than v1 one,
889 // (and no less than v1_size/4)
890 // thus making v1 preferable and possibly losing small details? should be ok
891 #define SMALLEST_CODEBOOK 1
892 for (v1enough
= 0, v1_size
= SMALLEST_CODEBOOK
; v1_size
<= CODEBOOK_MAX
&& !v1enough
; v1_size
<<= 2) {
893 for (v4enough
= 0, v4_size
= 0; v4_size
<= v1_size
&& !v4enough
; v4_size
= v4_size
? v4_size
<< 2 : v1_size
>= SMALLEST_CODEBOOK
<< 2 ? v1_size
>> 2 : SMALLEST_CODEBOOK
) {
896 for (mode
= 0; mode
< MODE_COUNT
; mode
++) {
897 // don't allow MODE_MC in intra frames
898 if (keyframe
&& mode
== MODE_MC
)
901 if (mode
== MODE_V1_ONLY
) {
902 info
.v1_size
= v1_size
;
903 // the size may shrink even before optimizations if the input is short:
904 info
.v1_size
= quantize(s
, h
, data
, linesize
, 1,
905 &info
, ENC_UNCERTAIN
);
906 if (info
.v1_size
< v1_size
)
907 // too few eligible blocks, no sense in trying bigger sizes
911 } else { // mode != MODE_V1_ONLY
912 // if v4 codebook is empty then only allow V1-only mode
916 if (mode
== MODE_V1_V4
) {
917 info
.v4_size
= v4_size
;
918 info
.v4_size
= quantize(s
, h
, data
, linesize
, 0,
919 &info
, ENC_UNCERTAIN
);
920 if (info
.v4_size
< v4_size
)
921 // too few eligible blocks, no sense in trying bigger sizes
927 // choose the best encoding per block, based on current experience
928 score
= calculate_mode_score(s
, h
, &info
, 0,
929 &v1shrunk
, &v4shrunk
);
931 if (mode
!= MODE_V1_ONLY
) {
932 int extra_iterations_limit
= s
->max_extra_cb_iterations
;
933 // recompute the codebooks, omitting the extra blocks
934 // we assume we _may_ come here with more blocks to encode than before
935 info
.v1_size
= v1_size
;
936 new_v1_size
= quantize(s
, h
, data
, linesize
, 1, &info
, ENC_V1
);
937 if (new_v1_size
< info
.v1_size
)
938 info
.v1_size
= new_v1_size
;
939 // we assume we _may_ come here with more blocks to encode than before
940 info
.v4_size
= v4_size
;
941 new_v4_size
= quantize(s
, h
, data
, linesize
, 0, &info
, ENC_V4
);
942 if (new_v4_size
< info
.v4_size
)
943 info
.v4_size
= new_v4_size
;
944 // calculate the resulting score
945 // (do not move blocks to codebook encodings now, as some blocks may have
946 // got bigger errors despite a smaller training set - but we do not
947 // ever grow the training sets back)
949 score
= calculate_mode_score(s
, h
, &info
, 1,
950 &v1shrunk
, &v4shrunk
);
951 // do we have a reason to reiterate? if so, have we reached the limit?
952 if ((!v1shrunk
&& !v4shrunk
) || !extra_iterations_limit
--)
954 // recompute the codebooks, omitting the extra blocks
956 info
.v1_size
= v1_size
;
957 new_v1_size
= quantize(s
, h
, data
, linesize
, 1, &info
, ENC_V1
);
958 if (new_v1_size
< info
.v1_size
)
959 info
.v1_size
= new_v1_size
;
962 info
.v4_size
= v4_size
;
963 new_v4_size
= quantize(s
, h
, data
, linesize
, 0, &info
, ENC_V4
);
964 if (new_v4_size
< info
.v4_size
)
965 info
.v4_size
= new_v4_size
;
970 if (best_size
== 0 || score
< *best_score
) {
972 best_size
= encode_mode(s
, h
,
973 scratch_data
, scratch_linesize
,
974 last_data
, last_linesize
, &info
,
975 s
->strip_buf
+ STRIP_HEADER_SIZE
);
977 write_strip_header(s
, y
, h
, keyframe
, s
->strip_buf
, best_size
);
983 best_size
+= STRIP_HEADER_SIZE
;
984 memcpy(buf
, s
->strip_buf
, best_size
);
989 static int write_cvid_header(CinepakEncContext
*s
, unsigned char *buf
,
990 int num_strips
, int data_size
, int isakeyframe
)
992 buf
[0] = isakeyframe
? 0 : 1;
993 AV_WB24(&buf
[1], data_size
+ CVID_HEADER_SIZE
);
994 AV_WB16(&buf
[4], s
->w
);
995 AV_WB16(&buf
[6], s
->h
);
996 AV_WB16(&buf
[8], num_strips
);
998 return CVID_HEADER_SIZE
;
1001 static int rd_frame(CinepakEncContext
*s
, const AVFrame
*frame
,
1002 int isakeyframe
, unsigned char *buf
, int buf_size
)
1004 int num_strips
, strip
, i
, y
, nexty
, size
, temp_size
, best_size
;
1005 uint8_t *last_data
[4], *data
[4], *scratch_data
[4];
1006 int last_linesize
[4], linesize
[4], scratch_linesize
[4];
1007 int64_t best_score
= 0, score
, score_temp
;
1010 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
1012 // build a copy of the given frame in the correct colorspace
1013 for (y
= 0; y
< s
->h
; y
+= 2)
1014 for (x
= 0; x
< s
->w
; x
+= 2) {
1016 int32_t r
, g
, b
, rr
, gg
, bb
;
1017 ir
[0] = frame
->data
[0] + x
* 3 + y
* frame
->linesize
[0];
1018 ir
[1] = ir
[0] + frame
->linesize
[0];
1019 get_sub_picture(s
, x
, y
,
1020 s
->input_frame
->data
, s
->input_frame
->linesize
,
1021 scratch_data
, scratch_linesize
);
1023 for (i
= 0; i
< 4; ++i
) {
1027 rr
= ir
[i2
][i1
* 3 + 0];
1028 gg
= ir
[i2
][i1
* 3 + 1];
1029 bb
= ir
[i2
][i1
* 3 + 2];
1033 // using fixed point arithmetic for portable repeatability, scaling by 2^23
1035 // rr = 0.2857 * rr + 0.5714 * gg + 0.1429 * bb;
1036 rr
= (2396625 * rr
+ 4793251 * gg
+ 1198732 * bb
) >> 23;
1041 scratch_data
[0][i1
+ i2
* scratch_linesize
[0]] = rr
;
1043 // let us scale down as late as possible
1044 // r /= 4; g /= 4; b /= 4;
1046 // rr = -0.1429 * r - 0.2857 * g + 0.4286 * b;
1047 rr
= (-299683 * r
- 599156 * g
+ 898839 * b
) >> 23;
1052 scratch_data
[1][0] = rr
+ 128; // quantize needs unsigned
1054 // rr = 0.3571 * r - 0.2857 * g - 0.0714 * b;
1055 rr
= (748893 * r
- 599156 * g
- 149737 * b
) >> 23;
1060 scratch_data
[2][0] = rr
+ 128; // quantize needs unsigned
1064 // would be nice but quite certainly incompatible with vintage players:
1065 // support encoding zero strips (meaning skip the whole frame)
1066 for (num_strips
= s
->min_strips
; num_strips
<= s
->max_strips
&& num_strips
<= s
->h
/ MB_SIZE
; num_strips
++) {
1070 for (y
= 0, strip
= 1; y
< s
->h
; strip
++, y
= nexty
) {
1073 nexty
= strip
* s
->h
/ num_strips
; // <= s->h
1074 // make nexty the next multiple of 4 if not already there
1076 nexty
+= 4 - (nexty
& 3);
1078 strip_height
= nexty
- y
;
1079 if (strip_height
<= 0) { // can this ever happen?
1080 av_log(s
->avctx
, AV_LOG_INFO
, "skipping zero height strip %i of %i\n", strip
, num_strips
);
1084 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
)
1085 get_sub_picture(s
, 0, y
,
1086 s
->input_frame
->data
, s
->input_frame
->linesize
,
1089 get_sub_picture(s
, 0, y
,
1090 (uint8_t **)frame
->data
, (int *)frame
->linesize
,
1092 get_sub_picture(s
, 0, y
,
1093 s
->last_frame
->data
, s
->last_frame
->linesize
,
1094 last_data
, last_linesize
);
1095 get_sub_picture(s
, 0, y
,
1096 s
->scratch_frame
->data
, s
->scratch_frame
->linesize
,
1097 scratch_data
, scratch_linesize
);
1099 if ((temp_size
= rd_strip(s
, y
, strip_height
, isakeyframe
,
1100 last_data
, last_linesize
, data
, linesize
,
1101 scratch_data
, scratch_linesize
,
1102 s
->frame_buf
+ size
+ CVID_HEADER_SIZE
,
1106 score
+= score_temp
;
1110 if (best_score
== 0 || score
< best_score
) {
1112 best_size
= size
+ write_cvid_header(s
, s
->frame_buf
, num_strips
, size
, isakeyframe
);
1114 FFSWAP(AVFrame
*, s
->best_frame
, s
->scratch_frame
);
1115 memcpy(buf
, s
->frame_buf
, best_size
);
1116 best_nstrips
= num_strips
;
1118 // avoid trying too many strip numbers without a real reason
1119 // (this makes the processing of the very first frame faster)
1120 if (num_strips
- best_nstrips
> 4)
1124 // let the number of strips slowly adapt to the changes in the contents,
1125 // compared to full bruteforcing every time this will occasionally lead
1126 // to some r/d performance loss but makes encoding up to several times faster
1127 if (!s
->strip_number_delta_range
) {
1128 if (best_nstrips
== s
->max_strips
) { // let us try to step up
1129 s
->max_strips
= best_nstrips
+ 1;
1130 if (s
->max_strips
>= s
->max_max_strips
)
1131 s
->max_strips
= s
->max_max_strips
;
1132 } else { // try to step down
1133 s
->max_strips
= best_nstrips
;
1135 s
->min_strips
= s
->max_strips
- 1;
1136 if (s
->min_strips
< s
->min_min_strips
)
1137 s
->min_strips
= s
->min_min_strips
;
1139 s
->max_strips
= best_nstrips
+ s
->strip_number_delta_range
;
1140 if (s
->max_strips
>= s
->max_max_strips
)
1141 s
->max_strips
= s
->max_max_strips
;
1142 s
->min_strips
= best_nstrips
- s
->strip_number_delta_range
;
1143 if (s
->min_strips
< s
->min_min_strips
)
1144 s
->min_strips
= s
->min_min_strips
;
1150 static int cinepak_encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
1151 const AVFrame
*frame
, int *got_packet
)
1153 CinepakEncContext
*s
= avctx
->priv_data
;
1156 s
->lambda
= frame
->quality
? frame
->quality
- 1 : 2 * FF_LAMBDA_SCALE
;
1158 if ((ret
= ff_alloc_packet(pkt
, s
->frame_buf_size
)) < 0)
1160 ret
= rd_frame(s
, frame
, (s
->curframe
== 0), pkt
->data
, s
->frame_buf_size
);
1162 if (s
->curframe
== 0)
1163 pkt
->flags
|= AV_PKT_FLAG_KEY
;
1166 FFSWAP(AVFrame
*, s
->last_frame
, s
->best_frame
);
1168 if (++s
->curframe
>= s
->keyint
)
1174 static av_cold
int cinepak_encode_end(AVCodecContext
*avctx
)
1176 CinepakEncContext
*s
= avctx
->priv_data
;
1179 av_frame_free(&s
->last_frame
);
1180 av_frame_free(&s
->best_frame
);
1181 av_frame_free(&s
->scratch_frame
);
1182 if (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
)
1183 av_frame_free(&s
->input_frame
);
1184 av_freep(&s
->codebook_input
);
1185 av_freep(&s
->codebook_closest
);
1186 av_freep(&s
->strip_buf
);
1187 av_freep(&s
->frame_buf
);
1190 for (x
= 0; x
< (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
? 4 : 3); x
++)
1191 av_freep(&s
->pict_bufs
[x
]);
1196 AVCodec ff_cinepak_encoder
= {
1198 .long_name
= NULL_IF_CONFIG_SMALL("Cinepak"),
1199 .type
= AVMEDIA_TYPE_VIDEO
,
1200 .id
= AV_CODEC_ID_CINEPAK
,
1201 .priv_data_size
= sizeof(CinepakEncContext
),
1202 .init
= cinepak_encode_init
,
1203 .encode2
= cinepak_encode_frame
,
1204 .close
= cinepak_encode_end
,
1205 .pix_fmts
= (const enum AVPixelFormat
[]) { AV_PIX_FMT_RGB24
, AV_PIX_FMT_GRAY8
, AV_PIX_FMT_NONE
},
1206 .priv_class
= &cinepak_class
,