2 * QuickTime RPZA Video Encoder
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * QT RPZA Video Encoder by Todd Kirby <doubleshot@pacbell.net> and David Adler
26 #include "libavutil/avassert.h"
27 #include "libavutil/common.h"
28 #include "libavutil/opt.h"
31 #include "codec_internal.h"
36 typedef struct RpzaContext
{
39 int skip_frame_thresh
;
40 int start_one_color_thresh
;
41 int continue_one_color_thresh
;
42 int sixteen_color_thresh
;
44 AVFrame
*prev_frame
; // buffer for previous source frame
45 PutBitContext pb
; // buffer for encoded frame data.
47 int frame_width
; // width in pixels of source frame
48 int frame_height
; // height in pixesl of source frame
50 int first_frame
; // flag set to one when the first frame is being processed
51 // so that comparisons with previous frame data in not attempted
54 typedef enum channel_offset
{
66 #define SQR(x) ((x) * (x))
68 /* 15 bit components */
69 #define GET_CHAN(color, chan) (((color) >> ((chan) * 5) & 0x1F))
70 #define R(color) GET_CHAN(color, RED)
71 #define G(color) GET_CHAN(color, GREEN)
72 #define B(color) GET_CHAN(color, BLUE)
74 typedef struct BlockInfo
{
89 static void get_colors(const uint8_t *min
, const uint8_t *max
, uint8_t color4
[4][3])
93 color4
[0][0] = min
[0];
94 color4
[0][1] = min
[1];
95 color4
[0][2] = min
[2];
97 color4
[3][0] = max
[0];
98 color4
[3][1] = max
[1];
99 color4
[3][2] = max
[2];
102 step
= (color4
[3][0] - color4
[0][0] + 1) / 3;
103 color4
[1][0] = color4
[0][0] + step
;
104 color4
[2][0] = color4
[3][0] - step
;
107 step
= (color4
[3][1] - color4
[0][1] + 1) / 3;
108 color4
[1][1] = color4
[0][1] + step
;
109 color4
[2][1] = color4
[3][1] - step
;
112 step
= (color4
[3][2] - color4
[0][2] + 1) / 3;
113 color4
[1][2] = color4
[0][2] + step
;
114 color4
[2][2] = color4
[3][2] - step
;
117 /* Fill BlockInfo struct with information about a 4x4 block of the image */
118 static int get_block_info(BlockInfo
*bi
, int block
, int prev_frame
)
120 bi
->row
= block
/ bi
->blocks_per_row
;
121 bi
->col
= block
% bi
->blocks_per_row
;
123 // test for right edge block
124 if (bi
->col
== bi
->blocks_per_row
- 1 && (bi
->image_width
% 4) != 0) {
125 bi
->block_width
= bi
->image_width
% 4;
130 // test for bottom edge block
131 if (bi
->row
== (bi
->image_height
/ 4) && (bi
->image_height
% 4) != 0) {
132 bi
->block_height
= bi
->image_height
% 4;
134 bi
->block_height
= 4;
137 return block
? (bi
->col
* 4) + (bi
->row
* (prev_frame
? bi
->prev_rowstride
: bi
->rowstride
) * 4) : 0;
140 static uint16_t rgb24_to_rgb555(const uint8_t *rgb24
)
157 * Returns the total difference between two 24 bit color values
159 static int diff_colors(const uint8_t *colorA
, const uint8_t *colorB
)
163 tot
= SQR(colorA
[0] - colorB
[0]);
164 tot
+= SQR(colorA
[1] - colorB
[1]);
165 tot
+= SQR(colorA
[2] - colorB
[2]);
171 * Returns the maximum channel difference
173 static int max_component_diff(const uint16_t *colorA
, const uint16_t *colorB
)
177 diff
= FFABS(R(colorA
[0]) - R(colorB
[0]));
181 diff
= FFABS(G(colorA
[0]) - G(colorB
[0]));
185 diff
= FFABS(B(colorA
[0]) - B(colorB
[0]));
193 * Find the channel that has the largest difference between minimum and maximum
194 * color values. Put the minimum value in min, maximum in max and the channel
197 static void get_max_component_diff(const BlockInfo
*bi
, const uint16_t *block_ptr
,
198 uint8_t *min
, uint8_t *max
, channel_offset
*chan
)
201 uint8_t min_r
, max_r
, min_g
, max_g
, min_b
, max_b
;
204 // fix warning about uninitialized vars
205 min_r
= min_g
= min_b
= UINT8_MAX
;
206 max_r
= max_g
= max_b
= 0;
208 // loop thru and compare pixels
209 for (y
= 0; y
< bi
->block_height
; y
++) {
210 for (x
= 0; x
< bi
->block_width
; x
++) {
212 min_r
= FFMIN(R(block_ptr
[x
]), min_r
);
213 min_g
= FFMIN(G(block_ptr
[x
]), min_g
);
214 min_b
= FFMIN(B(block_ptr
[x
]), min_b
);
216 max_r
= FFMAX(R(block_ptr
[x
]), max_r
);
217 max_g
= FFMAX(G(block_ptr
[x
]), max_g
);
218 max_b
= FFMAX(B(block_ptr
[x
]), max_b
);
220 block_ptr
+= bi
->rowstride
;
227 if (r
> g
&& r
> b
) {
231 } else if (g
> b
&& g
>= r
) {
243 * Compare two 4x4 blocks to determine if the total difference between the
244 * blocks is greater than the thresh parameter. Returns -1 if difference
245 * exceeds threshold or zero otherwise.
247 static int compare_blocks(const uint16_t *block1
, const uint16_t *block2
,
248 const BlockInfo
*bi
, int thresh
)
251 for (y
= 0; y
< bi
->block_height
; y
++) {
252 for (x
= 0; x
< bi
->block_width
; x
++) {
253 diff
= max_component_diff(&block1
[x
], &block2
[x
]);
254 if (diff
>= thresh
) {
258 block1
+= bi
->prev_rowstride
;
259 block2
+= bi
->rowstride
;
265 * Determine the fit of one channel to another within a 4x4 block. This
266 * is used to determine the best palette choices for 4-color encoding.
268 static int leastsquares(const uint16_t *block_ptr
, const BlockInfo
*bi
,
269 channel_offset xchannel
, channel_offset ychannel
,
270 int *slope
, int *y_intercept
, int *correlation_coef
)
272 int sumx
= 0, sumy
= 0, sumx2
= 0, sumy2
= 0, sumxy
= 0,
273 sumx_sq
= 0, sumy_sq
= 0, tmp
, tmp2
;
277 count
= bi
->block_height
* bi
->block_width
;
282 for (i
= 0; i
< bi
->block_height
; i
++) {
283 for (j
= 0; j
< bi
->block_width
; j
++) {
284 x
= GET_CHAN(block_ptr
[j
], xchannel
);
285 y
= GET_CHAN(block_ptr
[j
], ychannel
);
292 block_ptr
+= bi
->rowstride
;
295 sumx_sq
= sumx
* sumx
;
296 tmp
= (count
* sumx2
- sumx_sq
);
298 // guard against div/0
302 sumy_sq
= sumy
* sumy
;
304 *slope
= (sumx
* sumy
- sumxy
) / tmp
;
305 *y_intercept
= (sumy
- (*slope
) * sumx
) / count
;
307 tmp2
= count
* sumy2
- sumy_sq
;
309 *correlation_coef
= 0;
311 *correlation_coef
= (count
* sumxy
- sumx
* sumy
) /
312 ff_sqrt((unsigned)tmp
* tmp2
);
319 * Determine the amount of error in the leastsquares fit.
321 static int calc_lsq_max_fit_error(const uint16_t *block_ptr
, const BlockInfo
*bi
,
322 int min
, int max
, int tmp_min
, int tmp_max
,
323 channel_offset xchannel
, channel_offset ychannel
)
329 for (i
= 0; i
< bi
->block_height
; i
++) {
330 for (j
= 0; j
< bi
->block_width
; j
++) {
331 int x_inc
, lin_y
, lin_x
;
332 x
= GET_CHAN(block_ptr
[j
], xchannel
);
333 y
= GET_CHAN(block_ptr
[j
], ychannel
);
335 /* calculate x_inc as the 4-color index (0..3) */
336 x_inc
= (x
- min
) * 3 / (max
- min
) + 1;
337 x_inc
= FFMAX(FFMIN(3, x_inc
), 0);
339 /* calculate lin_y corresponding to x_inc */
340 lin_y
= tmp_min
+ (tmp_max
- tmp_min
) * x_inc
/ 3 + 1;
342 err
= FFABS(lin_y
- y
);
346 /* calculate lin_x corresponding to x_inc */
347 lin_x
= min
+ (max
- min
) * x_inc
/ 3 + 1;
349 err
= FFABS(lin_x
- x
);
353 block_ptr
+= bi
->rowstride
;
360 * Find the closest match to a color within the 4-color palette
362 static int match_color(const uint16_t *color
, uint8_t colors
[4][3])
365 int smallest_variance
= INT_MAX
;
366 uint8_t dithered_color
[3];
368 for (int channel
= 0; channel
< 3; channel
++) {
369 dithered_color
[channel
] = GET_CHAN(color
[0], channel
);
372 for (int palette_entry
= 0; palette_entry
< 4; palette_entry
++) {
373 int variance
= diff_colors(dithered_color
, colors
[palette_entry
]);
375 if (variance
< smallest_variance
) {
376 smallest_variance
= variance
;
385 * Encode a block using the 4-color opcode and palette. return number of
386 * blocks encoded (until we implement multi-block 4 color runs this will
389 static int encode_four_color_block(const uint8_t *min_color
, const uint8_t *max_color
,
390 PutBitContext
*pb
, const uint16_t *block_ptr
, const BlockInfo
*bi
)
392 const int y_size
= FFMIN(4, bi
->image_height
- bi
->row
* 4);
393 const int x_size
= FFMIN(4, bi
->image_width
- bi
->col
* 4);
394 uint8_t color4
[4][3];
395 uint16_t rounded_max
, rounded_min
;
398 // round min and max wider
399 rounded_min
= rgb24_to_rgb555(min_color
);
400 rounded_max
= rgb24_to_rgb555(max_color
);
402 // put a and b colors
403 // encode 4 colors = first 16 bit color with MSB zeroed and...
404 put_bits(pb
, 16, rounded_max
& ~0x8000);
405 // ...second 16 bit color with MSB on.
406 put_bits(pb
, 16, rounded_min
| 0x8000);
408 get_colors(min_color
, max_color
, color4
);
410 for (int y
= 0; y
< y_size
; y
++) {
411 for (int x
= 0; x
< x_size
; x
++) {
412 idx
= match_color(&block_ptr
[x
], color4
);
413 put_bits(pb
, 2, idx
);
416 for (int x
= x_size
; x
< 4; x
++)
417 put_bits(pb
, 2, idx
);
418 block_ptr
+= bi
->rowstride
;
421 for (int y
= y_size
; y
< 4; y
++) {
422 for (int x
= 0; x
< 4; x
++)
425 return 1; // num blocks encoded
429 * Copy a 4x4 block from the current frame buffer to the previous frame buffer.
431 static void update_block_in_prev_frame(const uint16_t *src_pixels
,
432 uint16_t *dest_pixels
,
433 const BlockInfo
*bi
, int block_counter
)
435 const int y_size
= FFMIN(4, bi
->image_height
- bi
->row
* 4);
436 const int x_size
= FFMIN(4, bi
->image_width
- bi
->col
* 4) * 2;
438 for (int y
= 0; y
< y_size
; y
++) {
439 memcpy(dest_pixels
, src_pixels
, x_size
);
440 dest_pixels
+= bi
->prev_rowstride
;
441 src_pixels
+= bi
->rowstride
;
446 * update statistics for the specified block. If first_block,
447 * it initializes the statistics. Otherwise it updates the statistics IF THIS
448 * BLOCK IS SUITABLE TO CONTINUE A 1-COLOR RUN. That is, it checks whether
449 * the range of colors (since the routine was called first_block != 0) are
450 * all close enough intensities to be represented by a single color.
452 * The routine returns 0 if this block is too different to be part of
453 * the same run of 1-color blocks. The routine returns 1 if this
454 * block can be part of the same 1-color block run.
456 * If the routine returns 1, it also updates its arguments to include
457 * the statistics of this block. Otherwise, the stats are unchanged
458 * and don't include the current block.
460 static int update_block_stats(RpzaContext
*s
, const BlockInfo
*bi
, const uint16_t *block
,
461 uint8_t min_color
[3], uint8_t max_color
[3],
462 int *total_rgb
, int *total_pixels
,
463 uint8_t avg_color
[3], int first_block
)
467 int total_pixels_blk
;
470 uint8_t min_color_blk
[3], max_color_blk
[3];
471 int total_rgb_blk
[3];
472 uint8_t avg_color_blk
[3];
475 min_color
[0] = UINT8_MAX
;
476 min_color
[1] = UINT8_MAX
;
477 min_color
[2] = UINT8_MAX
;
485 threshold
= s
->start_one_color_thresh
;
487 threshold
= s
->continue_one_color_thresh
;
491 The *_blk variables will include the current block.
492 Initialize them based on the blocks so far.
494 min_color_blk
[0] = min_color
[0];
495 min_color_blk
[1] = min_color
[1];
496 min_color_blk
[2] = min_color
[2];
497 max_color_blk
[0] = max_color
[0];
498 max_color_blk
[1] = max_color
[1];
499 max_color_blk
[2] = max_color
[2];
500 total_rgb_blk
[0] = total_rgb
[0];
501 total_rgb_blk
[1] = total_rgb
[1];
502 total_rgb_blk
[2] = total_rgb
[2];
503 total_pixels_blk
= *total_pixels
+ bi
->block_height
* bi
->block_width
;
506 Update stats for this block's pixels
508 for (y
= 0; y
< bi
->block_height
; y
++) {
509 for (x
= 0; x
< bi
->block_width
; x
++) {
510 total_rgb_blk
[0] += R(block
[x
]);
511 total_rgb_blk
[1] += G(block
[x
]);
512 total_rgb_blk
[2] += B(block
[x
]);
514 min_color_blk
[0] = FFMIN(R(block
[x
]), min_color_blk
[0]);
515 min_color_blk
[1] = FFMIN(G(block
[x
]), min_color_blk
[1]);
516 min_color_blk
[2] = FFMIN(B(block
[x
]), min_color_blk
[2]);
518 max_color_blk
[0] = FFMAX(R(block
[x
]), max_color_blk
[0]);
519 max_color_blk
[1] = FFMAX(G(block
[x
]), max_color_blk
[1]);
520 max_color_blk
[2] = FFMAX(B(block
[x
]), max_color_blk
[2]);
522 block
+= bi
->rowstride
;
526 Calculate average color including current block.
528 avg_color_blk
[0] = total_rgb_blk
[0] / total_pixels_blk
;
529 avg_color_blk
[1] = total_rgb_blk
[1] / total_pixels_blk
;
530 avg_color_blk
[2] = total_rgb_blk
[2] / total_pixels_blk
;
533 Are all the pixels within threshold of the average color?
535 is_in_range
= (max_color_blk
[0] - avg_color_blk
[0] <= threshold
&&
536 max_color_blk
[1] - avg_color_blk
[1] <= threshold
&&
537 max_color_blk
[2] - avg_color_blk
[2] <= threshold
&&
538 avg_color_blk
[0] - min_color_blk
[0] <= threshold
&&
539 avg_color_blk
[1] - min_color_blk
[1] <= threshold
&&
540 avg_color_blk
[2] - min_color_blk
[2] <= threshold
);
544 Set the output variables to include this block.
546 min_color
[0] = min_color_blk
[0];
547 min_color
[1] = min_color_blk
[1];
548 min_color
[2] = min_color_blk
[2];
549 max_color
[0] = max_color_blk
[0];
550 max_color
[1] = max_color_blk
[1];
551 max_color
[2] = max_color_blk
[2];
552 total_rgb
[0] = total_rgb_blk
[0];
553 total_rgb
[1] = total_rgb_blk
[1];
554 total_rgb
[2] = total_rgb_blk
[2];
555 *total_pixels
= total_pixels_blk
;
556 avg_color
[0] = avg_color_blk
[0];
557 avg_color
[1] = avg_color_blk
[1];
558 avg_color
[2] = avg_color_blk
[2];
564 static void rpza_encode_stream(RpzaContext
*s
, const AVFrame
*pict
)
567 int block_counter
= 0;
570 int prev_block_offset
;
571 int block_offset
= 0;
572 int pblock_offset
= 0;
573 uint8_t min
= 0, max
= 0;
576 int tmp_min
, tmp_max
;
578 uint8_t avg_color
[3];
580 uint8_t min_color
[3], max_color
[3];
581 int slope
, y_intercept
, correlation_coef
;
582 const uint16_t *src_pixels
= (const uint16_t *)pict
->data
[0];
583 uint16_t *prev_pixels
= (uint16_t *)s
->prev_frame
->data
[0];
585 /* Number of 4x4 blocks in frame. */
586 total_blocks
= ((s
->frame_width
+ 3) / 4) * ((s
->frame_height
+ 3) / 4);
588 bi
.image_width
= s
->frame_width
;
589 bi
.image_height
= s
->frame_height
;
590 bi
.rowstride
= pict
->linesize
[0] / 2;
591 bi
.prev_rowstride
= s
->prev_frame
->linesize
[0] / 2;
593 bi
.blocks_per_row
= (s
->frame_width
+ 3) / 4;
595 while (block_counter
< total_blocks
) {
597 // make sure we have a valid previous frame and we're not writing
599 if (!s
->first_frame
) {
601 prev_block_offset
= 0;
603 while (n_blocks
< 32 && block_counter
+ n_blocks
< total_blocks
) {
604 block_offset
= get_block_info(&bi
, block_counter
+ n_blocks
, 0);
605 pblock_offset
= get_block_info(&bi
, block_counter
+ n_blocks
, 1);
607 // multi-block opcodes cannot span multiple rows.
608 // If we're starting a new row, break out and write the opcode
609 /* TODO: Should eventually use bi.row here to determine when a
610 row break occurs, but that is currently breaking the
611 quicktime player. This is probably due to a bug in the
612 way I'm calculating the current row.
614 if (prev_block_offset
&& block_offset
- prev_block_offset
> 12) {
618 prev_block_offset
= block_offset
;
620 if (compare_blocks(&prev_pixels
[pblock_offset
],
621 &src_pixels
[block_offset
], &bi
, s
->skip_frame_thresh
) != 0) {
622 // write out skipable blocks
626 put_bits(&s
->pb
, 8, 0x80 | (n_blocks
- 1));
627 block_counter
+= n_blocks
;
635 * NOTE: we don't update skipped blocks in the previous frame buffer
636 * since skipped needs always to be compared against the first skipped
637 * block to avoid artifacts during gradual fade in/outs.
640 // update_block_in_prev_frame(&src_pixels[block_offset],
641 // &prev_pixels[pblock_offset], &bi, block_counter + n_blocks);
646 // we're either at the end of the frame or we've reached the maximum
647 // of 32 blocks in a run. Write out the run.
650 put_bits(&s
->pb
, 8, 0x80 | (n_blocks
- 1));
651 block_counter
+= n_blocks
;
657 block_offset
= get_block_info(&bi
, block_counter
, 0);
658 pblock_offset
= get_block_info(&bi
, block_counter
, 1);
663 if (update_block_stats(s
, &bi
, &src_pixels
[block_offset
],
664 min_color
, max_color
,
665 total_rgb
, &pixel_count
, avg_color
, 1)) {
666 prev_block_offset
= block_offset
;
670 /* update this block in the previous frame buffer */
671 update_block_in_prev_frame(&src_pixels
[block_offset
],
672 &prev_pixels
[pblock_offset
], &bi
, block_counter
+ n_blocks
);
674 // check for subsequent blocks with the same color
675 while (n_blocks
< 32 && block_counter
+ n_blocks
< total_blocks
) {
676 block_offset
= get_block_info(&bi
, block_counter
+ n_blocks
, 0);
677 pblock_offset
= get_block_info(&bi
, block_counter
+ n_blocks
, 1);
679 // multi-block opcodes cannot span multiple rows.
680 // If we've hit end of a row, break out and write the opcode
681 if (block_offset
- prev_block_offset
> 12) {
685 if (!update_block_stats(s
, &bi
, &src_pixels
[block_offset
],
686 min_color
, max_color
,
687 total_rgb
, &pixel_count
, avg_color
, 0)) {
691 prev_block_offset
= block_offset
;
693 /* update this block in the previous frame buffer */
694 update_block_in_prev_frame(&src_pixels
[block_offset
],
695 &prev_pixels
[pblock_offset
], &bi
, block_counter
+ n_blocks
);
700 // write one color opcode.
701 put_bits(&s
->pb
, 8, 0xa0 | (n_blocks
- 1));
702 // write color to encode.
703 put_bits(&s
->pb
, 16, rgb24_to_rgb555(avg_color
));
704 // skip past the blocks we've just encoded.
705 block_counter
+= n_blocks
;
706 } else { // FOUR COLOR CHECK
709 // get max component diff for block
710 get_max_component_diff(&bi
, &src_pixels
[block_offset
], &min
, &max
, &chan
);
719 // run least squares against other two components
720 for (i
= 0; i
< 3; i
++) {
727 slope
= y_intercept
= correlation_coef
= 0;
729 if (leastsquares(&src_pixels
[block_offset
], &bi
, chan
, i
,
730 &slope
, &y_intercept
, &correlation_coef
)) {
731 min_color
[i
] = GET_CHAN(src_pixels
[block_offset
], i
);
732 max_color
[i
] = GET_CHAN(src_pixels
[block_offset
], i
);
734 tmp_min
= 1 + min
* slope
+ y_intercept
;
735 tmp_max
= 1 + max
* slope
+ y_intercept
;
737 av_assert0(tmp_min
<= tmp_max
);
738 // clamp min and max color values
739 tmp_min
= av_clip_uint8(tmp_min
);
740 tmp_max
= av_clip_uint8(tmp_max
);
742 err
= FFMAX(calc_lsq_max_fit_error(&src_pixels
[block_offset
], &bi
,
743 min
, max
, tmp_min
, tmp_max
, chan
, i
), err
);
745 min_color
[i
] = tmp_min
;
746 max_color
[i
] = tmp_max
;
750 if (err
> s
->sixteen_color_thresh
) { // DO SIXTEEN COLOR BLOCK
751 const uint16_t *row_ptr
;
752 int y_size
, x_size
, rgb555
;
754 block_offset
= get_block_info(&bi
, block_counter
, 0);
755 pblock_offset
= get_block_info(&bi
, block_counter
, 1);
757 row_ptr
= &src_pixels
[block_offset
];
758 y_size
= FFMIN(4, bi
.image_height
- bi
.row
* 4);
759 x_size
= FFMIN(4, bi
.image_width
- bi
.col
* 4);
761 for (int y
= 0; y
< y_size
; y
++) {
762 for (int x
= 0; x
< x_size
; x
++) {
763 rgb555
= row_ptr
[x
] & ~0x8000;
765 put_bits(&s
->pb
, 16, rgb555
);
767 for (int x
= x_size
; x
< 4; x
++)
768 put_bits(&s
->pb
, 16, 0);
770 row_ptr
+= bi
.rowstride
;
773 for (int y
= y_size
; y
< 4; y
++) {
774 for (int x
= 0; x
< 4; x
++)
775 put_bits(&s
->pb
, 16, 0);
779 } else { // FOUR COLOR BLOCK
780 block_counter
+= encode_four_color_block(min_color
, max_color
,
781 &s
->pb
, &src_pixels
[block_offset
], &bi
);
784 /* update this block in the previous frame buffer */
785 update_block_in_prev_frame(&src_pixels
[block_offset
],
786 &prev_pixels
[pblock_offset
], &bi
, block_counter
);
791 static int rpza_encode_init(AVCodecContext
*avctx
)
793 RpzaContext
*s
= avctx
->priv_data
;
795 s
->frame_width
= avctx
->width
;
796 s
->frame_height
= avctx
->height
;
798 s
->prev_frame
= av_frame_alloc();
800 return AVERROR(ENOMEM
);
805 static int rpza_encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
806 const AVFrame
*pict
, int *got_packet
)
808 RpzaContext
*s
= avctx
->priv_data
;
810 int ret
= ff_alloc_packet(avctx
, pkt
, 4LL + 6LL * FFMAX(avctx
->height
, 4) * FFMAX(avctx
->width
, 4));
815 init_put_bits(&s
->pb
, pkt
->data
, pkt
->size
);
817 // skip 4 byte header, write it later once the size of the chunk is known
818 put_bits32(&s
->pb
, 0x00);
820 if (!s
->prev_frame
->data
[0]) {
822 s
->prev_frame
->format
= pict
->format
;
823 s
->prev_frame
->width
= pict
->width
;
824 s
->prev_frame
->height
= pict
->height
;
825 ret
= av_frame_get_buffer(s
->prev_frame
, 0);
832 rpza_encode_stream(s
, pict
);
834 flush_put_bits(&s
->pb
);
836 av_shrink_packet(pkt
, put_bytes_output(&s
->pb
));
839 // write header opcode
840 buf
[0] = 0xe1; // chunk opcode
842 // write chunk length
843 AV_WB24(buf
+ 1, pkt
->size
);
850 static int rpza_encode_end(AVCodecContext
*avctx
)
852 RpzaContext
*s
= (RpzaContext
*)avctx
->priv_data
;
854 av_frame_free(&s
->prev_frame
);
859 #define OFFSET(x) offsetof(RpzaContext, x)
860 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
861 static const AVOption options
[] = {
862 { "skip_frame_thresh", NULL
, OFFSET(skip_frame_thresh
), AV_OPT_TYPE_INT
, {.i64
=1}, 0, 24, VE
},
863 { "start_one_color_thresh", NULL
, OFFSET(start_one_color_thresh
), AV_OPT_TYPE_INT
, {.i64
=1}, 0, 24, VE
},
864 { "continue_one_color_thresh", NULL
, OFFSET(continue_one_color_thresh
), AV_OPT_TYPE_INT
, {.i64
=0}, 0, 24, VE
},
865 { "sixteen_color_thresh", NULL
, OFFSET(sixteen_color_thresh
), AV_OPT_TYPE_INT
, {.i64
=1}, 0, 24, VE
},
869 static const AVClass rpza_class
= {
870 .class_name
= "rpza",
871 .item_name
= av_default_item_name
,
873 .version
= LIBAVUTIL_VERSION_INT
,
876 const FFCodec ff_rpza_encoder
= {
878 CODEC_LONG_NAME("QuickTime video (RPZA)"),
879 .p
.type
= AVMEDIA_TYPE_VIDEO
,
880 .p
.id
= AV_CODEC_ID_RPZA
,
881 .p
.capabilities
= AV_CODEC_CAP_DR1
| AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
,
882 .priv_data_size
= sizeof(RpzaContext
),
883 .p
.priv_class
= &rpza_class
,
884 .init
= rpza_encode_init
,
885 FF_CODEC_ENCODE_CB(rpza_encode_frame
),
886 .close
= rpza_encode_end
,
887 .p
.pix_fmts
= (const enum AVPixelFormat
[]) { AV_PIX_FMT_RGB555
,