|
|
@ -31,7 +31,8 @@ typedef struct SgiContext { |
|
|
|
AVFrame picture; |
|
|
|
AVFrame picture; |
|
|
|
} SgiContext; |
|
|
|
} SgiContext; |
|
|
|
|
|
|
|
|
|
|
|
static av_cold int encode_init(AVCodecContext *avctx){ |
|
|
|
static av_cold int encode_init(AVCodecContext *avctx) |
|
|
|
|
|
|
|
{ |
|
|
|
SgiContext *s = avctx->priv_data; |
|
|
|
SgiContext *s = avctx->priv_data; |
|
|
|
|
|
|
|
|
|
|
|
avcodec_get_frame_defaults(&s->picture); |
|
|
|
avcodec_get_frame_defaults(&s->picture); |
|
|
@ -41,7 +42,8 @@ static av_cold int encode_init(AVCodecContext *avctx){ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, |
|
|
|
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, |
|
|
|
int buf_size, void *data) { |
|
|
|
int buf_size, void *data) |
|
|
|
|
|
|
|
{ |
|
|
|
SgiContext *s = avctx->priv_data; |
|
|
|
SgiContext *s = avctx->priv_data; |
|
|
|
AVFrame * const p = &s->picture; |
|
|
|
AVFrame * const p = &s->picture; |
|
|
|
uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf; |
|
|
|
uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf; |
|
|
@ -53,24 +55,24 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, |
|
|
|
p->pict_type = FF_I_TYPE; |
|
|
|
p->pict_type = FF_I_TYPE; |
|
|
|
p->key_frame = 1; |
|
|
|
p->key_frame = 1; |
|
|
|
|
|
|
|
|
|
|
|
width = avctx->width; |
|
|
|
width = avctx->width; |
|
|
|
height = avctx->height; |
|
|
|
height = avctx->height; |
|
|
|
|
|
|
|
|
|
|
|
switch (avctx->pix_fmt) { |
|
|
|
switch (avctx->pix_fmt) { |
|
|
|
case PIX_FMT_GRAY8: |
|
|
|
case PIX_FMT_GRAY8: |
|
|
|
dimension = SGI_SINGLE_CHAN; |
|
|
|
dimension = SGI_SINGLE_CHAN; |
|
|
|
depth = SGI_GRAYSCALE; |
|
|
|
depth = SGI_GRAYSCALE; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case PIX_FMT_RGB24: |
|
|
|
case PIX_FMT_RGB24: |
|
|
|
dimension = SGI_MULTI_CHAN; |
|
|
|
dimension = SGI_MULTI_CHAN; |
|
|
|
depth = SGI_RGB; |
|
|
|
depth = SGI_RGB; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case PIX_FMT_RGBA: |
|
|
|
case PIX_FMT_RGBA: |
|
|
|
dimension = SGI_MULTI_CHAN; |
|
|
|
dimension = SGI_MULTI_CHAN; |
|
|
|
depth = SGI_RGBA; |
|
|
|
depth = SGI_RGBA; |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
tablesize = depth * height * 4; |
|
|
|
tablesize = depth * height * 4; |
|
|
@ -107,51 +109,51 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, |
|
|
|
offsettab = buf; |
|
|
|
offsettab = buf; |
|
|
|
|
|
|
|
|
|
|
|
if (avctx->coder_type != FF_CODER_TYPE_RAW) { |
|
|
|
if (avctx->coder_type != FF_CODER_TYPE_RAW) { |
|
|
|
/* Skip RLE offset table. */ |
|
|
|
/* Skip RLE offset table. */ |
|
|
|
buf += tablesize; |
|
|
|
buf += tablesize; |
|
|
|
lengthtab = buf; |
|
|
|
lengthtab = buf; |
|
|
|
|
|
|
|
|
|
|
|
/* Skip RLE length table. */ |
|
|
|
/* Skip RLE length table. */ |
|
|
|
buf += tablesize; |
|
|
|
buf += tablesize; |
|
|
|
|
|
|
|
|
|
|
|
/* Make an intermediate consecutive buffer. */ |
|
|
|
/* Make an intermediate consecutive buffer. */ |
|
|
|
if ((encode_buf = av_malloc(width)) == NULL) |
|
|
|
if ((encode_buf = av_malloc(width)) == NULL) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
for (z = 0; z < depth; z++) { |
|
|
|
for (z = 0; z < depth; z++) { |
|
|
|
in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; |
|
|
|
in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; |
|
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < height; y++) { |
|
|
|
for (y = 0; y < height; y++) { |
|
|
|
bytestream_put_be32(&offsettab, buf - orig_buf); |
|
|
|
bytestream_put_be32(&offsettab, buf - orig_buf); |
|
|
|
|
|
|
|
|
|
|
|
for (x = 0; x < width; x++) |
|
|
|
for (x = 0; x < width; x++) |
|
|
|
encode_buf[x] = in_buf[depth * x]; |
|
|
|
encode_buf[x] = in_buf[depth * x]; |
|
|
|
|
|
|
|
|
|
|
|
if((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) { |
|
|
|
if ((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) { |
|
|
|
av_free(encode_buf); |
|
|
|
av_free(encode_buf); |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
buf += length; |
|
|
|
buf += length; |
|
|
|
bytestream_put_byte(&buf, 0); |
|
|
|
bytestream_put_byte(&buf, 0); |
|
|
|
bytestream_put_be32(&lengthtab, length + 1); |
|
|
|
bytestream_put_be32(&lengthtab, length + 1); |
|
|
|
in_buf -= p->linesize[0]; |
|
|
|
in_buf -= p->linesize[0]; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
av_free(encode_buf); |
|
|
|
av_free(encode_buf); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
for (z = 0; z < depth; z++) { |
|
|
|
for (z = 0; z < depth; z++) { |
|
|
|
in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; |
|
|
|
in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; |
|
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < height; y++) { |
|
|
|
for (y = 0; y < height; y++) { |
|
|
|
for (x = 0; x < width * depth; x += depth) |
|
|
|
for (x = 0; x < width * depth; x += depth) |
|
|
|
bytestream_put_byte(&buf, in_buf[x]); |
|
|
|
bytestream_put_byte(&buf, in_buf[x]); |
|
|
|
|
|
|
|
|
|
|
|
in_buf -= p->linesize[0]; |
|
|
|
in_buf -= p->linesize[0]; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* total length */ |
|
|
|
/* total length */ |
|
|
|
return buf - orig_buf; |
|
|
|
return buf - orig_buf; |
|
|
@ -168,4 +170,3 @@ AVCodec sgi_encoder = { |
|
|
|
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA, PIX_FMT_GRAY8, PIX_FMT_NONE}, |
|
|
|
.pix_fmts= (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA, PIX_FMT_GRAY8, PIX_FMT_NONE}, |
|
|
|
.long_name= NULL_IF_CONFIG_SMALL("SGI image"), |
|
|
|
.long_name= NULL_IF_CONFIG_SMALL("SGI image"), |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|