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/intreadwrite.h"
41 #include "libavutil/lfg.h"
42 #include "libavutil/mem.h"
43 #include "libavutil/opt.h"
46 #include "codec_internal.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 const AVClass
*class;
106 AVCodecContext
*avctx
;
107 unsigned char *pict_bufs
[4], *strip_buf
, *frame_buf
;
110 AVFrame
*scratch_frame
;
111 AVFrame
*input_frame
;
112 enum AVPixelFormat pix_fmt
;
119 int *codebook_closest
;
120 mb_info
*mb
; // MB RD state
121 int min_strips
; // the current limit
122 int max_strips
; // the current limit
124 int max_extra_cb_iterations
;
128 int strip_number_delta_range
;
129 struct ELBGContext
*elbg
;
132 #define OFFSET(x) offsetof(CinepakEncContext, x)
133 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
134 static const AVOption options
[] = {
135 { "max_extra_cb_iterations", "Max extra codebook recalculation passes, more is better and slower",
136 OFFSET(max_extra_cb_iterations
), AV_OPT_TYPE_INT
, { .i64
= 2 }, 0, INT_MAX
, VE
},
137 { "skip_empty_cb", "Avoid wasting bytes, ignore vintage MacOS decoder",
138 OFFSET(skip_empty_cb
), AV_OPT_TYPE_BOOL
, { .i64
= 0 }, 0, 1, VE
},
139 { "max_strips", "Limit strips/frame, vintage compatible is 1..3, otherwise the more the better",
140 OFFSET(max_max_strips
), AV_OPT_TYPE_INT
, { .i64
= 3 }, MIN_STRIPS
, MAX_STRIPS
, VE
},
141 { "min_strips", "Enforce min strips/frame, more is worse and faster, must be <= max_strips",
142 OFFSET(min_min_strips
), AV_OPT_TYPE_INT
, { .i64
= MIN_STRIPS
}, MIN_STRIPS
, MAX_STRIPS
, VE
},
143 { "strip_number_adaptivity", "How fast the strip number adapts, more is slightly better, much slower",
144 OFFSET(strip_number_delta_range
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, MAX_STRIPS
- MIN_STRIPS
, VE
},
148 static const AVClass cinepak_class
= {
149 .class_name
= "cinepak",
150 .item_name
= av_default_item_name
,
152 .version
= LIBAVUTIL_VERSION_INT
,
155 static av_cold
int cinepak_encode_init(AVCodecContext
*avctx
)
157 CinepakEncContext
*s
= avctx
->priv_data
;
158 int x
, mb_count
, strip_buf_size
, frame_buf_size
;
160 if (avctx
->width
& 3 || avctx
->height
& 3) {
161 av_log(avctx
, AV_LOG_ERROR
, "width and height must be multiples of four (got %ix%i)\n",
162 avctx
->width
, avctx
->height
);
163 return AVERROR(EINVAL
);
166 if (s
->min_min_strips
> s
->max_max_strips
) {
167 av_log(avctx
, AV_LOG_ERROR
, "minimum number of strips must not exceed maximum (got %i and %i)\n",
168 s
->min_min_strips
, s
->max_max_strips
);
169 return AVERROR(EINVAL
);
172 if (!(s
->last_frame
= av_frame_alloc()))
173 return AVERROR(ENOMEM
);
174 if (!(s
->best_frame
= av_frame_alloc()))
175 return AVERROR(ENOMEM
);
176 if (!(s
->scratch_frame
= av_frame_alloc()))
177 return AVERROR(ENOMEM
);
178 if (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
)
179 if (!(s
->input_frame
= av_frame_alloc()))
180 return AVERROR(ENOMEM
);
182 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 return AVERROR(ENOMEM
);
185 if (!(s
->codebook_closest
= av_malloc_array((avctx
->width
* avctx
->height
) >> 2, sizeof(*s
->codebook_closest
))))
186 return AVERROR(ENOMEM
);
188 for (x
= 0; x
< (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
? 4 : 3); x
++)
189 if (!(s
->pict_bufs
[x
] = av_malloc((avctx
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4) * (avctx
->width
* avctx
->height
) >> 2)))
190 return AVERROR(ENOMEM
);
192 mb_count
= avctx
->width
* avctx
->height
/ MB_AREA
;
194 // the largest possible chunk is 0x31 with all MBs encoded in V4 mode
195 // and full codebooks being replaced in INTER mode,
196 // which is 34 bits per MB
197 // and 2*256 extra flag bits per strip
198 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;
200 frame_buf_size
= CVID_HEADER_SIZE
+ s
->max_max_strips
* strip_buf_size
;
202 if (!(s
->strip_buf
= av_malloc(strip_buf_size
)))
203 return AVERROR(ENOMEM
);
205 if (!(s
->frame_buf
= av_malloc(frame_buf_size
)))
206 return AVERROR(ENOMEM
);
208 if (!(s
->mb
= av_malloc_array(mb_count
, sizeof(mb_info
))))
209 return AVERROR(ENOMEM
);
211 av_lfg_init(&s
->randctx
, 1);
214 s
->h
= avctx
->height
;
215 s
->frame_buf_size
= frame_buf_size
;
217 s
->pix_fmt
= avctx
->pix_fmt
;
220 s
->last_frame
->data
[0] = s
->pict_bufs
[0];
221 s
->last_frame
->linesize
[0] = s
->w
;
222 s
->best_frame
->data
[0] = s
->pict_bufs
[1];
223 s
->best_frame
->linesize
[0] = s
->w
;
224 s
->scratch_frame
->data
[0] = s
->pict_bufs
[2];
225 s
->scratch_frame
->linesize
[0] = s
->w
;
227 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
228 s
->last_frame
->data
[1] = s
->last_frame
->data
[0] + s
->w
* s
->h
;
229 s
->last_frame
->data
[2] = s
->last_frame
->data
[1] + ((s
->w
* s
->h
) >> 2);
230 s
->last_frame
->linesize
[1] =
231 s
->last_frame
->linesize
[2] = s
->w
>> 1;
233 s
->best_frame
->data
[1] = s
->best_frame
->data
[0] + s
->w
* s
->h
;
234 s
->best_frame
->data
[2] = s
->best_frame
->data
[1] + ((s
->w
* s
->h
) >> 2);
235 s
->best_frame
->linesize
[1] =
236 s
->best_frame
->linesize
[2] = s
->w
>> 1;
238 s
->scratch_frame
->data
[1] = s
->scratch_frame
->data
[0] + s
->w
* s
->h
;
239 s
->scratch_frame
->data
[2] = s
->scratch_frame
->data
[1] + ((s
->w
* s
->h
) >> 2);
240 s
->scratch_frame
->linesize
[1] =
241 s
->scratch_frame
->linesize
[2] = s
->w
>> 1;
243 s
->input_frame
->data
[0] = s
->pict_bufs
[3];
244 s
->input_frame
->linesize
[0] = s
->w
;
245 s
->input_frame
->data
[1] = s
->input_frame
->data
[0] + s
->w
* s
->h
;
246 s
->input_frame
->data
[2] = s
->input_frame
->data
[1] + ((s
->w
* s
->h
) >> 2);
247 s
->input_frame
->linesize
[1] =
248 s
->input_frame
->linesize
[2] = s
->w
>> 1;
251 s
->min_strips
= s
->min_min_strips
;
252 s
->max_strips
= s
->max_max_strips
;
257 static int64_t calculate_mode_score(CinepakEncContext
*s
, int h
,
258 strip_info
*info
, int report
,
259 int *training_set_v1_shrunk
,
260 int *training_set_v4_shrunk
)
262 // score = FF_LAMBDA_SCALE * error + lambda * bits
264 int entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
265 int mb_count
= s
->w
* h
/ MB_AREA
;
267 int64_t score1
, score2
, score3
;
268 int64_t ret
= s
->lambda
* ((info
->v1_size
? CHUNK_HEADER_SIZE
+ info
->v1_size
* entry_size
: 0) +
269 (info
->v4_size
? CHUNK_HEADER_SIZE
+ info
->v4_size
* entry_size
: 0) +
270 CHUNK_HEADER_SIZE
) << 3;
272 switch (info
->mode
) {
275 ret
+= s
->lambda
* 8 * mb_count
;
277 // while calculating we assume all blocks are ENC_V1
278 for (x
= 0; x
< mb_count
; x
++) {
280 ret
+= FF_LAMBDA_SCALE
* mb
->v1_error
;
281 // this function is never called for report in MODE_V1_ONLY
283 mb
->best_encoding
= ENC_V1
;
288 // 9 or 33 bits per MB
290 // no moves between the corresponding training sets are allowed
291 *training_set_v1_shrunk
= *training_set_v4_shrunk
= 0;
292 for (x
= 0; x
< mb_count
; x
++) {
295 if (mb
->best_encoding
== ENC_V1
)
296 score1
= s
->lambda
* 9 + FF_LAMBDA_SCALE
* (mberr
= mb
->v1_error
);
298 score1
= s
->lambda
* 33 + FF_LAMBDA_SCALE
* (mberr
= mb
->v4_error
);
301 } else { // find best mode per block
302 for (x
= 0; x
< mb_count
; x
++) {
304 score1
= s
->lambda
* 9 + FF_LAMBDA_SCALE
* mb
->v1_error
;
305 score2
= s
->lambda
* 33 + FF_LAMBDA_SCALE
* mb
->v4_error
;
307 if (score1
<= score2
) {
309 mb
->best_encoding
= ENC_V1
;
312 mb
->best_encoding
= ENC_V4
;
319 // 1, 10 or 34 bits per MB
321 int v1_shrunk
= 0, v4_shrunk
= 0;
322 for (x
= 0; x
< mb_count
; x
++) {
324 // it is OK to move blocks to ENC_SKIP here
325 // but not to any codebook encoding!
326 score1
= s
->lambda
* 1 + FF_LAMBDA_SCALE
* mb
->skip_error
;
327 if (mb
->best_encoding
== ENC_SKIP
) {
329 } else if (mb
->best_encoding
== ENC_V1
) {
330 if ((score2
= s
->lambda
* 10 + FF_LAMBDA_SCALE
* mb
->v1_error
) >= score1
) {
331 mb
->best_encoding
= ENC_SKIP
;
338 if ((score3
= s
->lambda
* 34 + FF_LAMBDA_SCALE
* mb
->v4_error
) >= score1
) {
339 mb
->best_encoding
= ENC_SKIP
;
347 *training_set_v1_shrunk
= v1_shrunk
;
348 *training_set_v4_shrunk
= v4_shrunk
;
349 } else { // find best mode per block
350 for (x
= 0; x
< mb_count
; x
++) {
352 score1
= s
->lambda
* 1 + FF_LAMBDA_SCALE
* mb
->skip_error
;
353 score2
= s
->lambda
* 10 + FF_LAMBDA_SCALE
* mb
->v1_error
;
354 score3
= s
->lambda
* 34 + FF_LAMBDA_SCALE
* mb
->v4_error
;
356 if (score1
<= score2
&& score1
<= score3
) {
358 mb
->best_encoding
= ENC_SKIP
;
359 } else if (score2
<= score3
) {
361 mb
->best_encoding
= ENC_V1
;
364 mb
->best_encoding
= ENC_V4
;
375 static int write_chunk_header(unsigned char *buf
, int chunk_type
, int chunk_size
)
378 AV_WB24(&buf
[1], chunk_size
+ CHUNK_HEADER_SIZE
);
379 return CHUNK_HEADER_SIZE
;
382 static int encode_codebook(CinepakEncContext
*s
, int *codebook
, int size
,
383 int chunk_type_yuv
, int chunk_type_gray
,
386 int x
, y
, ret
, entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
387 int incremental_codebook_replacement_mode
= 0; // hardcoded here,
388 // the compiler should notice that this is a constant -- rl
390 ret
= write_chunk_header(buf
,
391 s
->pix_fmt
== AV_PIX_FMT_RGB24
?
392 chunk_type_yuv
+ (incremental_codebook_replacement_mode
? 1 : 0) :
393 chunk_type_gray
+ (incremental_codebook_replacement_mode
? 1 : 0),
395 (incremental_codebook_replacement_mode
? (size
+ 31) / 32 * 4 : 0));
397 // we do codebook encoding according to the "intra" mode
398 // but we keep the "dead" code for reference in case we will want
399 // to use incremental codebook updates (which actually would give us
400 // "kind of" motion compensation, especially in 1 strip/frame case) -- rl
401 // (of course, the code will be not useful as-is)
402 if (incremental_codebook_replacement_mode
) {
405 for (x
= 0; x
< size
; x
++) {
411 flags
= ((flags
>> 1) | 0x80000000);
412 for (y
= 0; y
< entry_size
; y
++)
413 buf
[ret
++] = codebook
[y
+ x
* entry_size
] ^ (y
>= 4 ? 0x80 : 0);
414 if ((flags
& 0xffffffff) == 0xffffffff) {
415 AV_WB32(&buf
[flagsind
], flags
);
420 AV_WB32(&buf
[flagsind
], flags
);
422 for (x
= 0; x
< size
; x
++)
423 for (y
= 0; y
< entry_size
; y
++)
424 buf
[ret
++] = codebook
[y
+ x
* entry_size
] ^ (y
>= 4 ? 0x80 : 0);
429 // sets out to the sub picture starting at (x,y) in in
430 static void get_sub_picture(CinepakEncContext
*s
, int x
, int y
,
431 uint8_t *const in_data
[4], const int in_linesize
[4],
432 uint8_t *out_data
[4], int out_linesize
[4])
434 out_data
[0] = in_data
[0] + x
+ y
* in_linesize
[0];
435 out_linesize
[0] = in_linesize
[0];
437 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
438 out_data
[1] = in_data
[1] + (x
>> 1) + (y
>> 1) * in_linesize
[1];
439 out_linesize
[1] = in_linesize
[1];
441 out_data
[2] = in_data
[2] + (x
>> 1) + (y
>> 1) * in_linesize
[2];
442 out_linesize
[2] = in_linesize
[2];
446 // decodes the V1 vector in mb into the 4x4 MB pointed to by data
447 static void decode_v1_vector(CinepakEncContext
*s
, uint8_t *data
[4],
448 int linesize
[4], int v1_vector
, strip_info
*info
)
450 int entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
454 data
[0][ linesize
[0]] =
455 data
[0][1 + linesize
[0]] = info
->v1_codebook
[v1_vector
* entry_size
];
459 data
[0][2 + linesize
[0]] =
460 data
[0][3 + linesize
[0]] = info
->v1_codebook
[v1_vector
* entry_size
+ 1];
462 data
[0][ 2 * linesize
[0]] =
463 data
[0][1 + 2 * linesize
[0]] =
464 data
[0][ 3 * linesize
[0]] =
465 data
[0][1 + 3 * linesize
[0]] = info
->v1_codebook
[v1_vector
* entry_size
+ 2];
467 data
[0][2 + 2 * linesize
[0]] =
468 data
[0][3 + 2 * linesize
[0]] =
469 data
[0][2 + 3 * linesize
[0]] =
470 data
[0][3 + 3 * linesize
[0]] = info
->v1_codebook
[v1_vector
* entry_size
+ 3];
472 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
475 data
[1][ linesize
[1]] =
476 data
[1][1 + linesize
[1]] = info
->v1_codebook
[v1_vector
* entry_size
+ 4];
480 data
[2][ linesize
[2]] =
481 data
[2][1 + linesize
[2]] = info
->v1_codebook
[v1_vector
* entry_size
+ 5];
485 // decodes the V4 vectors in mb into the 4x4 MB pointed to by data
486 static void decode_v4_vector(CinepakEncContext
*s
, uint8_t *data
[4],
487 int linesize
[4], int *v4_vector
, strip_info
*info
)
489 int i
, x
, y
, entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
491 for (i
= y
= 0; y
< 4; y
+= 2) {
492 for (x
= 0; x
< 4; x
+= 2, i
++) {
493 data
[0][x
+ y
* linesize
[0]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
];
494 data
[0][x
+ 1 + y
* linesize
[0]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 1];
495 data
[0][x
+ (y
+ 1) * linesize
[0]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 2];
496 data
[0][x
+ 1 + (y
+ 1) * linesize
[0]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 3];
498 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
499 data
[1][(x
>> 1) + (y
>> 1) * linesize
[1]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 4];
500 data
[2][(x
>> 1) + (y
>> 1) * linesize
[2]] = info
->v4_codebook
[v4_vector
[i
] * entry_size
+ 5];
506 static void copy_mb(CinepakEncContext
*s
,
507 uint8_t *a_data
[4], int a_linesize
[4],
508 uint8_t *b_data
[4], int b_linesize
[4])
512 for (y
= 0; y
< MB_SIZE
; y
++)
513 memcpy(a_data
[0] + y
* a_linesize
[0], b_data
[0] + y
* b_linesize
[0],
516 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
517 for (p
= 1; p
<= 2; p
++)
518 for (y
= 0; y
< MB_SIZE
/ 2; y
++)
519 memcpy(a_data
[p
] + y
* a_linesize
[p
],
520 b_data
[p
] + y
* b_linesize
[p
],
525 static int encode_mode(CinepakEncContext
*s
, int h
,
526 uint8_t *scratch_data
[4], int scratch_linesize
[4],
527 uint8_t *last_data
[4], int last_linesize
[4],
528 strip_info
*info
, unsigned char *buf
)
530 int x
, y
, z
, bits
, temp_size
, header_ofs
, ret
= 0, mb_count
= s
->w
* h
/ MB_AREA
;
531 int needs_extra_bit
, should_write_temp
;
533 unsigned char temp
[64]; // 32/2 = 16 V4 blocks at 4 B each -> 64 B
535 uint8_t *sub_scratch_data
[4] = { 0 }, *sub_last_data
[4] = { 0 };
536 int sub_scratch_linesize
[4] = { 0 }, sub_last_linesize
[4] = { 0 };
539 ////// MacOS vintage decoder compatibility dictates the presence of
540 ////// the codebook chunk even when the codebook is empty - pretty dumb...
541 ////// and also the certain order of the codebook chunks -- rl
542 if (info
->v4_size
|| !s
->skip_empty_cb
)
543 ret
+= encode_codebook(s
, info
->v4_codebook
, info
->v4_size
, 0x20, 0x24, buf
+ ret
);
545 if (info
->v1_size
|| !s
->skip_empty_cb
)
546 ret
+= encode_codebook(s
, info
->v1_codebook
, info
->v1_size
, 0x22, 0x26, buf
+ ret
);
548 // update scratch picture
549 for (z
= y
= 0; y
< h
; y
+= MB_SIZE
)
550 for (x
= 0; x
< s
->w
; x
+= MB_SIZE
, z
++) {
553 get_sub_picture(s
, x
, y
, scratch_data
, scratch_linesize
,
554 sub_scratch_data
, sub_scratch_linesize
);
556 if (info
->mode
== MODE_MC
&& mb
->best_encoding
== ENC_SKIP
) {
557 get_sub_picture(s
, x
, y
, last_data
, last_linesize
,
558 sub_last_data
, sub_last_linesize
);
559 copy_mb(s
, sub_scratch_data
, sub_scratch_linesize
,
560 sub_last_data
, sub_last_linesize
);
561 } else if (info
->mode
== MODE_V1_ONLY
|| mb
->best_encoding
== ENC_V1
)
562 decode_v1_vector(s
, sub_scratch_data
, sub_scratch_linesize
,
563 mb
->v1_vector
, info
);
565 decode_v4_vector(s
, sub_scratch_data
, sub_scratch_linesize
,
566 mb
->v4_vector
, info
);
569 switch (info
->mode
) {
571 ret
+= write_chunk_header(buf
+ ret
, 0x32, mb_count
);
573 for (x
= 0; x
< mb_count
; x
++)
574 buf
[ret
++] = s
->mb
[x
].v1_vector
;
578 // remember header position
580 ret
+= CHUNK_HEADER_SIZE
;
582 for (x
= 0; x
< mb_count
; x
+= 32) {
584 for (y
= x
; y
< FFMIN(x
+ 32, mb_count
); y
++)
585 if (s
->mb
[y
].best_encoding
== ENC_V4
)
586 flags
|= 1U << (31 - y
+ x
);
588 AV_WB32(&buf
[ret
], flags
);
591 for (y
= x
; y
< FFMIN(x
+ 32, mb_count
); y
++) {
594 if (mb
->best_encoding
== ENC_V1
)
595 buf
[ret
++] = mb
->v1_vector
;
597 for (z
= 0; z
< 4; z
++)
598 buf
[ret
++] = mb
->v4_vector
[z
];
602 write_chunk_header(buf
+ header_ofs
, 0x30, ret
- header_ofs
- CHUNK_HEADER_SIZE
);
606 // remember header position
608 ret
+= CHUNK_HEADER_SIZE
;
609 flags
= bits
= temp_size
= 0;
611 for (x
= 0; x
< mb_count
; x
++) {
613 flags
|= (uint32_t)(mb
->best_encoding
!= ENC_SKIP
) << (31 - bits
++);
615 should_write_temp
= 0;
617 if (mb
->best_encoding
!= ENC_SKIP
) {
619 flags
|= (uint32_t)(mb
->best_encoding
== ENC_V4
) << (31 - bits
++);
625 AV_WB32(&buf
[ret
], flags
);
629 if (mb
->best_encoding
== ENC_SKIP
|| needs_extra_bit
) {
630 memcpy(&buf
[ret
], temp
, temp_size
);
634 should_write_temp
= 1;
637 if (needs_extra_bit
) {
638 flags
= (uint32_t)(mb
->best_encoding
== ENC_V4
) << 31;
642 if (mb
->best_encoding
== ENC_V1
)
643 temp
[temp_size
++] = mb
->v1_vector
;
644 else if (mb
->best_encoding
== ENC_V4
)
645 for (z
= 0; z
< 4; z
++)
646 temp
[temp_size
++] = mb
->v4_vector
[z
];
648 if (should_write_temp
) {
649 memcpy(&buf
[ret
], temp
, temp_size
);
656 AV_WB32(&buf
[ret
], flags
);
658 memcpy(&buf
[ret
], temp
, temp_size
);
662 write_chunk_header(buf
+ header_ofs
, 0x31, ret
- header_ofs
- CHUNK_HEADER_SIZE
);
670 // computes distortion of 4x4 MB in b compared to a
671 static int compute_mb_distortion(CinepakEncContext
*s
,
672 uint8_t *a_data
[4], int a_linesize
[4],
673 uint8_t *b_data
[4], int b_linesize
[4])
675 int x
, y
, p
, d
, ret
= 0;
677 for (y
= 0; y
< MB_SIZE
; y
++)
678 for (x
= 0; x
< MB_SIZE
; x
++) {
679 d
= a_data
[0][x
+ y
* a_linesize
[0]] - b_data
[0][x
+ y
* b_linesize
[0]];
683 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
684 for (p
= 1; p
<= 2; p
++) {
685 for (y
= 0; y
< MB_SIZE
/ 2; y
++)
686 for (x
= 0; x
< MB_SIZE
/ 2; x
++) {
687 d
= a_data
[p
][x
+ y
* a_linesize
[p
]] - b_data
[p
][x
+ y
* b_linesize
[p
]];
696 // return the possibly adjusted size of the codebook
697 #define CERTAIN(x) ((x) != ENC_UNCERTAIN)
698 static int quantize(CinepakEncContext
*s
, int h
, uint8_t *data
[4],
699 int linesize
[4], int v1mode
, strip_info
*info
,
700 mb_encoding encoding
)
702 int x
, y
, i
, j
, k
, x2
, y2
, x3
, y3
, plane
, shift
, mbn
;
703 int entry_size
= s
->pix_fmt
== AV_PIX_FMT_RGB24
? 6 : 4;
704 int *codebook
= v1mode
? info
->v1_codebook
: info
->v4_codebook
;
705 int size
= v1mode
? info
->v1_size
: info
->v4_size
;
706 uint8_t vq_pict_buf
[(MB_AREA
* 3) / 2];
707 uint8_t *sub_data
[4], *vq_data
[4];
708 int sub_linesize
[4], vq_linesize
[4];
711 for (mbn
= i
= y
= 0; y
< h
; y
+= MB_SIZE
) {
712 for (x
= 0; x
< s
->w
; x
+= MB_SIZE
, ++mbn
) {
715 if (CERTAIN(encoding
)) {
716 // use for the training only the blocks known to be to be encoded [sic:-]
717 if (s
->mb
[mbn
].best_encoding
!= encoding
)
721 base
= s
->codebook_input
+ i
* entry_size
;
724 for (j
= y2
= 0; y2
< entry_size
; y2
+= 2)
725 for (x2
= 0; x2
< 4; x2
+= 2, j
++) {
726 plane
= y2
< 4 ? 0 : 1 + (x2
>> 1);
727 shift
= y2
< 4 ? 0 : 1;
730 base
[j
] = (data
[plane
][((x
+ x3
) >> shift
) + ((y
+ y3
) >> shift
) * linesize
[plane
]] +
731 data
[plane
][((x
+ x3
) >> shift
) + 1 + ((y
+ y3
) >> shift
) * linesize
[plane
]] +
732 data
[plane
][((x
+ x3
) >> shift
) + (((y
+ y3
) >> shift
) + 1) * linesize
[plane
]] +
733 data
[plane
][((x
+ x3
) >> shift
) + 1 + (((y
+ y3
) >> shift
) + 1) * linesize
[plane
]]) >> 2;
737 for (j
= y2
= 0; y2
< MB_SIZE
; y2
+= 2) {
738 for (x2
= 0; x2
< MB_SIZE
; x2
+= 2)
739 for (k
= 0; k
< entry_size
; k
++, j
++) {
740 plane
= k
>= 4 ? k
- 3 : 0;
746 x3
= x
+ x2
+ (k
& 1);
747 y3
= y
+ y2
+ (k
>> 1);
750 base
[j
] = data
[plane
][x3
+ y3
* linesize
[plane
]];
758 if (i
== 0) // empty training set, nothing to do
763 ret
= avpriv_elbg_do(&s
->elbg
, s
->codebook_input
, entry_size
, i
, codebook
,
764 size
, 1, s
->codebook_closest
, &s
->randctx
, 0);
768 // set up vq_data, which contains a single MB
769 vq_data
[0] = vq_pict_buf
;
770 vq_linesize
[0] = MB_SIZE
;
771 vq_data
[1] = &vq_pict_buf
[MB_AREA
];
772 vq_data
[2] = vq_data
[1] + (MB_AREA
>> 2);
774 vq_linesize
[2] = MB_SIZE
>> 1;
777 for (i
= j
= y
= 0; y
< h
; y
+= MB_SIZE
)
778 for (x
= 0; x
< s
->w
; x
+= MB_SIZE
, j
++) {
779 mb_info
*mb
= &s
->mb
[j
];
780 // skip uninteresting blocks if we know their preferred encoding
781 if (CERTAIN(encoding
) && mb
->best_encoding
!= encoding
)
784 // point sub_data to current MB
785 get_sub_picture(s
, x
, y
, data
, linesize
, sub_data
, sub_linesize
);
788 mb
->v1_vector
= s
->codebook_closest
[i
];
790 // fill in vq_data with V1 data
791 decode_v1_vector(s
, vq_data
, vq_linesize
, mb
->v1_vector
, info
);
793 mb
->v1_error
= compute_mb_distortion(s
, sub_data
, sub_linesize
,
794 vq_data
, vq_linesize
);
796 for (k
= 0; k
< 4; k
++)
797 mb
->v4_vector
[k
] = s
->codebook_closest
[i
+ k
];
799 // fill in vq_data with V4 data
800 decode_v4_vector(s
, vq_data
, vq_linesize
, mb
->v4_vector
, info
);
802 mb
->v4_error
= compute_mb_distortion(s
, sub_data
, sub_linesize
,
803 vq_data
, vq_linesize
);
807 // check that we did it right in the beginning of the function
808 av_assert0(i
>= size
); // training set is no smaller than the codebook
813 static void calculate_skip_errors(CinepakEncContext
*s
, int h
,
814 uint8_t *last_data
[4], int last_linesize
[4],
815 uint8_t *data
[4], int linesize
[4],
819 uint8_t *sub_last_data
[4], *sub_pict_data
[4];
820 int sub_last_linesize
[4], sub_pict_linesize
[4];
822 for (i
= y
= 0; y
< h
; y
+= MB_SIZE
)
823 for (x
= 0; x
< s
->w
; x
+= MB_SIZE
, i
++) {
824 get_sub_picture(s
, x
, y
, last_data
, last_linesize
,
825 sub_last_data
, sub_last_linesize
);
826 get_sub_picture(s
, x
, y
, data
, linesize
,
827 sub_pict_data
, sub_pict_linesize
);
829 s
->mb
[i
].skip_error
=
830 compute_mb_distortion(s
,
831 sub_last_data
, sub_last_linesize
,
832 sub_pict_data
, sub_pict_linesize
);
836 static void write_strip_keyframe(unsigned char *buf
, int keyframe
)
838 // actually we are exclusively using intra strip coding (how much can we win
839 // otherwise? how to choose which part of a codebook to update?),
840 // keyframes are different only because we disallow ENC_SKIP on them -- rl
841 // (besides, the logic here used to be inverted: )
842 // buf[0] = keyframe ? 0x11: 0x10;
843 buf
[0] = keyframe
? 0x10 : 0x11;
846 static void write_strip_header(CinepakEncContext
*s
, int y
, int h
, int keyframe
,
847 unsigned char *buf
, int strip_size
)
849 write_strip_keyframe(buf
, keyframe
);
850 AV_WB24(&buf
[1], strip_size
+ STRIP_HEADER_SIZE
);
851 // AV_WB16(&buf[4], y); /* using absolute y values works -- rl */
852 AV_WB16(&buf
[4], 0); /* using relative values works as well -- rl */
854 // AV_WB16(&buf[8], y + h); /* using absolute y values works -- rl */
855 AV_WB16(&buf
[8], h
); /* using relative values works as well -- rl */
856 AV_WB16(&buf
[10], s
->w
);
859 static int rd_strip(CinepakEncContext
*s
, int y
, int h
, int keyframe
,
860 uint8_t *last_data
[4], int last_linesize
[4],
861 uint8_t *data
[4], int linesize
[4],
862 uint8_t *scratch_data
[4], int scratch_linesize
[4],
863 unsigned char *buf
, int64_t *best_score
, int *no_skip
)
868 // for codebook optimization:
869 int v1enough
, v1_size
, v4enough
, v4_size
;
870 int new_v1_size
, new_v4_size
;
871 int v1shrunk
, v4shrunk
;
874 calculate_skip_errors(s
, h
, last_data
, last_linesize
, data
, linesize
,
877 // try some powers of 4 for the size of the codebooks
878 // constraint the v4 codebook to be no bigger than v1 one,
879 // (and no less than v1_size/4)
880 // thus making v1 preferable and possibly losing small details? should be ok
881 #define SMALLEST_CODEBOOK 1
882 for (v1enough
= 0, v1_size
= SMALLEST_CODEBOOK
; v1_size
<= CODEBOOK_MAX
&& !v1enough
; v1_size
<<= 2) {
883 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
) {
886 for (mode
= 0; mode
< MODE_COUNT
; mode
++) {
887 // don't allow MODE_MC in intra frames
888 if (keyframe
&& mode
== MODE_MC
)
891 if (mode
== MODE_V1_ONLY
) {
892 info
.v1_size
= v1_size
;
893 // the size may shrink even before optimizations if the input is short:
894 if ((new_v1_size
= quantize(s
, h
, data
, linesize
, 1,
895 &info
, ENC_UNCERTAIN
)) < 0)
897 info
.v1_size
= new_v1_size
;
898 if (info
.v1_size
< v1_size
)
899 // too few eligible blocks, no sense in trying bigger sizes
903 } else { // mode != MODE_V1_ONLY
904 // if v4 codebook is empty then only allow V1-only mode
908 if (mode
== MODE_V1_V4
) {
909 info
.v4_size
= v4_size
;
910 new_v4_size
= quantize(s
, h
, data
, linesize
, 0,
911 &info
, ENC_UNCERTAIN
);
914 info
.v4_size
= new_v4_size
;
915 if (info
.v4_size
< v4_size
)
916 // too few eligible blocks, no sense in trying bigger sizes
922 // choose the best encoding per block, based on current experience
923 score
= calculate_mode_score(s
, h
, &info
, 0,
924 &v1shrunk
, &v4shrunk
);
926 if (mode
!= MODE_V1_ONLY
) {
927 int extra_iterations_limit
= s
->max_extra_cb_iterations
;
928 // recompute the codebooks, omitting the extra blocks
929 // we assume we _may_ come here with more blocks to encode than before
930 info
.v1_size
= v1_size
;
931 new_v1_size
= quantize(s
, h
, data
, linesize
, 1, &info
, ENC_V1
);
934 if (new_v1_size
< info
.v1_size
)
935 info
.v1_size
= new_v1_size
;
936 // we assume we _may_ come here with more blocks to encode than before
937 info
.v4_size
= v4_size
;
938 new_v4_size
= quantize(s
, h
, data
, linesize
, 0, &info
, ENC_V4
);
941 if (new_v4_size
< info
.v4_size
)
942 info
.v4_size
= new_v4_size
;
943 // calculate the resulting score
944 // (do not move blocks to codebook encodings now, as some blocks may have
945 // got bigger errors despite a smaller training set - but we do not
946 // ever grow the training sets back)
948 score
= calculate_mode_score(s
, h
, &info
, 1,
949 &v1shrunk
, &v4shrunk
);
950 // do we have a reason to reiterate? if so, have we reached the limit?
951 if ((!v1shrunk
&& !v4shrunk
) || !extra_iterations_limit
--)
953 // recompute the codebooks, omitting the extra blocks
955 info
.v1_size
= v1_size
;
956 new_v1_size
= quantize(s
, h
, data
, linesize
, 1, &info
, ENC_V1
);
959 if (new_v1_size
< info
.v1_size
)
960 info
.v1_size
= new_v1_size
;
963 info
.v4_size
= v4_size
;
964 new_v4_size
= quantize(s
, h
, data
, linesize
, 0, &info
, ENC_V4
);
967 if (new_v4_size
< info
.v4_size
)
968 info
.v4_size
= new_v4_size
;
973 if (best_size
== 0 || score
< *best_score
) {
975 best_size
= encode_mode(s
, h
,
976 scratch_data
, scratch_linesize
,
977 last_data
, last_linesize
, &info
,
978 s
->strip_buf
+ STRIP_HEADER_SIZE
);
979 // in theory we could have MODE_MC without ENC_SKIP,
980 // but MODE_V1_V4 will always be more efficient
981 *no_skip
= info
.mode
!= MODE_MC
;
983 write_strip_header(s
, y
, h
, keyframe
, s
->strip_buf
, best_size
);
989 best_size
+= STRIP_HEADER_SIZE
;
990 memcpy(buf
, s
->strip_buf
, best_size
);
995 static int write_cvid_header(CinepakEncContext
*s
, unsigned char *buf
,
996 int num_strips
, int data_size
, int isakeyframe
)
998 buf
[0] = isakeyframe
? 0 : 1;
999 AV_WB24(&buf
[1], data_size
+ CVID_HEADER_SIZE
);
1000 AV_WB16(&buf
[4], s
->w
);
1001 AV_WB16(&buf
[6], s
->h
);
1002 AV_WB16(&buf
[8], num_strips
);
1004 return CVID_HEADER_SIZE
;
1007 static int rd_frame(CinepakEncContext
*s
, const AVFrame
*frame
,
1008 int isakeyframe
, unsigned char *buf
, int buf_size
, int *got_keyframe
)
1010 int num_strips
, strip
, i
, y
, nexty
, size
, temp_size
, best_size
;
1011 uint8_t *last_data
[4], *data
[4], *scratch_data
[4];
1012 int last_linesize
[4], linesize
[4], scratch_linesize
[4];
1013 int64_t best_score
= 0, score
, score_temp
;
1014 int best_nstrips
, best_strip_offsets
[MAX_STRIPS
];
1016 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
) {
1018 // build a copy of the given frame in the correct colorspace
1019 for (y
= 0; y
< s
->h
; y
+= 2)
1020 for (x
= 0; x
< s
->w
; x
+= 2) {
1021 const uint8_t *ir
[2];
1022 int32_t r
, g
, b
, rr
, gg
, bb
;
1023 ir
[0] = frame
->data
[0] + x
* 3 + y
* frame
->linesize
[0];
1024 ir
[1] = ir
[0] + frame
->linesize
[0];
1025 get_sub_picture(s
, x
, y
,
1026 s
->input_frame
->data
, s
->input_frame
->linesize
,
1027 scratch_data
, scratch_linesize
);
1029 for (i
= 0; i
< 4; ++i
) {
1033 rr
= ir
[i2
][i1
* 3 + 0];
1034 gg
= ir
[i2
][i1
* 3 + 1];
1035 bb
= ir
[i2
][i1
* 3 + 2];
1039 // using fixed point arithmetic for portable repeatability, scaling by 2^23
1041 // rr = 0.2857 * rr + 0.5714 * gg + 0.1429 * bb;
1042 rr
= (2396625 * rr
+ 4793251 * gg
+ 1198732 * bb
) >> 23;
1047 scratch_data
[0][i1
+ i2
* scratch_linesize
[0]] = rr
;
1049 // let us scale down as late as possible
1050 // r /= 4; g /= 4; b /= 4;
1052 // rr = -0.1429 * r - 0.2857 * g + 0.4286 * b;
1053 rr
= (-299683 * r
- 599156 * g
+ 898839 * b
) >> 23;
1058 scratch_data
[1][0] = rr
+ 128; // quantize needs unsigned
1060 // rr = 0.3571 * r - 0.2857 * g - 0.0714 * b;
1061 rr
= (748893 * r
- 599156 * g
- 149737 * b
) >> 23;
1066 scratch_data
[2][0] = rr
+ 128; // quantize needs unsigned
1070 // would be nice but quite certainly incompatible with vintage players:
1071 // support encoding zero strips (meaning skip the whole frame)
1072 for (num_strips
= s
->min_strips
; num_strips
<= s
->max_strips
&& num_strips
<= s
->h
/ MB_SIZE
; num_strips
++) {
1073 int strip_offsets
[MAX_STRIPS
];
1074 int all_no_skip
= 1;
1078 for (y
= 0, strip
= 1; y
< s
->h
; strip
++, y
= nexty
) {
1079 int strip_height
, no_skip
;
1081 strip_offsets
[strip
-1] = size
+ CVID_HEADER_SIZE
;
1082 nexty
= strip
* s
->h
/ num_strips
; // <= s->h
1083 // make nexty the next multiple of 4 if not already there
1085 nexty
+= 4 - (nexty
& 3);
1087 strip_height
= nexty
- y
;
1088 if (strip_height
<= 0) { // can this ever happen?
1089 av_log(s
->avctx
, AV_LOG_INFO
, "skipping zero height strip %i of %i\n", strip
, num_strips
);
1093 if (s
->pix_fmt
== AV_PIX_FMT_RGB24
)
1094 get_sub_picture(s
, 0, y
,
1095 s
->input_frame
->data
, s
->input_frame
->linesize
,
1098 get_sub_picture(s
, 0, y
,
1099 frame
->data
, frame
->linesize
,
1101 get_sub_picture(s
, 0, y
,
1102 s
->last_frame
->data
, s
->last_frame
->linesize
,
1103 last_data
, last_linesize
);
1104 get_sub_picture(s
, 0, y
,
1105 s
->scratch_frame
->data
, s
->scratch_frame
->linesize
,
1106 scratch_data
, scratch_linesize
);
1108 if ((temp_size
= rd_strip(s
, y
, strip_height
, isakeyframe
,
1109 last_data
, last_linesize
, data
, linesize
,
1110 scratch_data
, scratch_linesize
,
1111 s
->frame_buf
+ strip_offsets
[strip
-1],
1112 &score_temp
, &no_skip
)) < 0)
1115 score
+= score_temp
;
1117 all_no_skip
&= no_skip
;
1120 if (best_score
== 0 || score
< best_score
) {
1122 best_size
= size
+ write_cvid_header(s
, s
->frame_buf
, num_strips
, size
, all_no_skip
);
1124 FFSWAP(AVFrame
*, s
->best_frame
, s
->scratch_frame
);
1125 memcpy(buf
, s
->frame_buf
, best_size
);
1126 best_nstrips
= num_strips
;
1127 *got_keyframe
= all_no_skip
; // no skip MBs in any strip -> keyframe
1128 memcpy(best_strip_offsets
, strip_offsets
, sizeof(strip_offsets
));
1130 // avoid trying too many strip numbers without a real reason
1131 // (this makes the processing of the very first frame faster)
1132 if (num_strips
- best_nstrips
> 4)
1136 // update strip headers
1137 for (i
= 0; i
< best_nstrips
; i
++) {
1138 write_strip_keyframe(s
->frame_buf
+ best_strip_offsets
[i
], *got_keyframe
);
1141 // let the number of strips slowly adapt to the changes in the contents,
1142 // compared to full bruteforcing every time this will occasionally lead
1143 // to some r/d performance loss but makes encoding up to several times faster
1144 if (!s
->strip_number_delta_range
) {
1145 if (best_nstrips
== s
->max_strips
) { // let us try to step up
1146 s
->max_strips
= best_nstrips
+ 1;
1147 if (s
->max_strips
>= s
->max_max_strips
)
1148 s
->max_strips
= s
->max_max_strips
;
1149 } else { // try to step down
1150 s
->max_strips
= best_nstrips
;
1152 s
->min_strips
= s
->max_strips
- 1;
1153 if (s
->min_strips
< s
->min_min_strips
)
1154 s
->min_strips
= s
->min_min_strips
;
1156 s
->max_strips
= best_nstrips
+ s
->strip_number_delta_range
;
1157 if (s
->max_strips
>= s
->max_max_strips
)
1158 s
->max_strips
= s
->max_max_strips
;
1159 s
->min_strips
= best_nstrips
- s
->strip_number_delta_range
;
1160 if (s
->min_strips
< s
->min_min_strips
)
1161 s
->min_strips
= s
->min_min_strips
;
1167 static int cinepak_encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
1168 const AVFrame
*frame
, int *got_packet
)
1170 CinepakEncContext
*s
= avctx
->priv_data
;
1171 int ret
, got_keyframe
;
1173 s
->lambda
= frame
->quality
? frame
->quality
- 1 : 2 * FF_LAMBDA_SCALE
;
1175 if ((ret
= ff_alloc_packet(avctx
, pkt
, s
->frame_buf_size
)) < 0)
1177 ret
= rd_frame(s
, frame
, (s
->curframe
== 0), pkt
->data
, s
->frame_buf_size
, &got_keyframe
);
1180 pkt
->flags
|= AV_PKT_FLAG_KEY
;
1185 FFSWAP(AVFrame
*, s
->last_frame
, s
->best_frame
);
1187 if (++s
->curframe
>= avctx
->gop_size
)
1193 static av_cold
int cinepak_encode_end(AVCodecContext
*avctx
)
1195 CinepakEncContext
*s
= avctx
->priv_data
;
1198 avpriv_elbg_free(&s
->elbg
);
1199 av_frame_free(&s
->last_frame
);
1200 av_frame_free(&s
->best_frame
);
1201 av_frame_free(&s
->scratch_frame
);
1202 if (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
)
1203 av_frame_free(&s
->input_frame
);
1204 av_freep(&s
->codebook_input
);
1205 av_freep(&s
->codebook_closest
);
1206 av_freep(&s
->strip_buf
);
1207 av_freep(&s
->frame_buf
);
1210 for (x
= 0; x
< (avctx
->pix_fmt
== AV_PIX_FMT_RGB24
? 4 : 3); x
++)
1211 av_freep(&s
->pict_bufs
[x
]);
1216 const FFCodec ff_cinepak_encoder
= {
1217 .p
.name
= "cinepak",
1218 CODEC_LONG_NAME("Cinepak"),
1219 .p
.type
= AVMEDIA_TYPE_VIDEO
,
1220 .p
.id
= AV_CODEC_ID_CINEPAK
,
1221 .p
.capabilities
= AV_CODEC_CAP_DR1
| AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
,
1222 .priv_data_size
= sizeof(CinepakEncContext
),
1223 .init
= cinepak_encode_init
,
1224 FF_CODEC_ENCODE_CB(cinepak_encode_frame
),
1225 .close
= cinepak_encode_end
,
1226 .p
.pix_fmts
= (const enum AVPixelFormat
[]) { AV_PIX_FMT_RGB24
, AV_PIX_FMT_GRAY8
, AV_PIX_FMT_NONE
},
1227 .p
.priv_class
= &cinepak_class
,
1228 .caps_internal
= FF_CODEC_CAP_INIT_CLEANUP
,