|
|
|
@@ -39,6 +39,7 @@ typedef struct QtrleEncContext { |
|
|
|
int pixel_size; |
|
|
|
AVPicture previous_frame; |
|
|
|
unsigned int max_buf_size; |
|
|
|
int logical_width; |
|
|
|
/** |
|
|
|
* This array will contain at ith position the value of the best RLE code |
|
|
|
* if the line started at pixel i |
|
|
|
@@ -67,8 +68,13 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) |
|
|
|
return -1; |
|
|
|
} |
|
|
|
s->avctx=avctx; |
|
|
|
s->logical_width=avctx->width; |
|
|
|
|
|
|
|
switch (avctx->pix_fmt) { |
|
|
|
case PIX_FMT_GRAY8: |
|
|
|
s->logical_width = avctx->width / 4; |
|
|
|
s->pixel_size = 4; |
|
|
|
break; |
|
|
|
case PIX_FMT_RGB555BE: |
|
|
|
s->pixel_size = 2; |
|
|
|
break; |
|
|
|
@@ -82,11 +88,11 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n"); |
|
|
|
break; |
|
|
|
} |
|
|
|
avctx->bits_per_coded_sample = s->pixel_size*8; |
|
|
|
avctx->bits_per_coded_sample = avctx->pix_fmt == PIX_FMT_GRAY8 ? 40 : s->pixel_size*8; |
|
|
|
|
|
|
|
s->rlecode_table = av_mallocz(s->avctx->width); |
|
|
|
s->skip_table = av_mallocz(s->avctx->width); |
|
|
|
s->length_table = av_mallocz((s->avctx->width + 1)*sizeof(int)); |
|
|
|
s->rlecode_table = av_mallocz(s->logical_width); |
|
|
|
s->skip_table = av_mallocz(s->logical_width); |
|
|
|
s->length_table = av_mallocz((s->logical_width + 1)*sizeof(int)); |
|
|
|
if (!s->skip_table || !s->length_table || !s->rlecode_table) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n"); |
|
|
|
return -1; |
|
|
|
@@ -96,10 +102,10 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
s->max_buf_size = s->avctx->width*s->avctx->height*s->pixel_size /* image base material */ |
|
|
|
+ 15 /* header + footer */ |
|
|
|
+ s->avctx->height*2 /* skip code+rle end */ |
|
|
|
+ s->avctx->width/MAX_RLE_BULK + 1 /* rle codes */; |
|
|
|
s->max_buf_size = s->logical_width*s->avctx->height*s->pixel_size /* image base material */ |
|
|
|
+ 15 /* header + footer */ |
|
|
|
+ s->avctx->height*2 /* skip code+rle end */ |
|
|
|
+ s->logical_width/MAX_RLE_BULK + 1 /* rle codes */; |
|
|
|
avctx->coded_frame = &s->frame; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
@@ -109,7 +115,7 @@ static av_cold int qtrle_encode_init(AVCodecContext *avctx) |
|
|
|
*/ |
|
|
|
static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t **buf) |
|
|
|
{ |
|
|
|
int width=s->avctx->width; |
|
|
|
int width=s->logical_width; |
|
|
|
int i; |
|
|
|
signed char rlecode; |
|
|
|
|
|
|
|
@@ -224,12 +230,26 @@ static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t |
|
|
|
} |
|
|
|
else if (rlecode > 0) { |
|
|
|
/* bulk copy */ |
|
|
|
bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size); |
|
|
|
if (s->avctx->pix_fmt == PIX_FMT_GRAY8) { |
|
|
|
// QT grayscale colorspace has 0=white and 255=black, we will |
|
|
|
// ignore the palette that is included in the AVFrame because |
|
|
|
// PIX_FMT_GRAY8 has defined color mapping |
|
|
|
for (int j = 0; j < rlecode*s->pixel_size; ++j) |
|
|
|
bytestream_put_byte(buf, *(this_line + i*s->pixel_size + j) ^ 0xff); |
|
|
|
} else { |
|
|
|
bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size); |
|
|
|
} |
|
|
|
i += rlecode; |
|
|
|
} |
|
|
|
else { |
|
|
|
/* repeat the bits */ |
|
|
|
bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size); |
|
|
|
if (s->avctx->pix_fmt == PIX_FMT_GRAY8) { |
|
|
|
// QT grayscale colorspace has 0=white and 255=black, ... |
|
|
|
for (int j = 0; j < s->pixel_size; ++j) |
|
|
|
bytestream_put_byte(buf, *(this_line + i*s->pixel_size + j) ^ 0xff); |
|
|
|
} else { |
|
|
|
bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size); |
|
|
|
} |
|
|
|
i -= rlecode; |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -245,7 +265,7 @@ static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf) |
|
|
|
uint8_t *orig_buf = buf; |
|
|
|
|
|
|
|
if (!s->frame.key_frame) { |
|
|
|
unsigned line_size = s->avctx->width * s->pixel_size; |
|
|
|
unsigned line_size = s->logical_width * s->pixel_size; |
|
|
|
for (start_line = 0; start_line < s->avctx->height; start_line++) |
|
|
|
if (memcmp(p->data[0] + start_line*p->linesize[0], |
|
|
|
s->previous_frame.data[0] + start_line*s->previous_frame.linesize[0], |
|
|
|
@@ -329,6 +349,6 @@ AVCodec ff_qtrle_encoder = { |
|
|
|
qtrle_encode_init, |
|
|
|
qtrle_encode_frame, |
|
|
|
qtrle_encode_end, |
|
|
|
.pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB555BE, PIX_FMT_ARGB, PIX_FMT_NONE}, |
|
|
|
.pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB555BE, PIX_FMT_ARGB, PIX_FMT_GRAY8, PIX_FMT_NONE}, |
|
|
|
.long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), |
|
|
|
}; |