| @@ -21,6 +21,7 @@ | |||||
| #include "avcodec.h" | #include "avcodec.h" | ||||
| #include "bytestream.h" | #include "bytestream.h" | ||||
| #include "internal.h" | |||||
| #include "sgi.h" | #include "sgi.h" | ||||
| #include "rle.h" | #include "rle.h" | ||||
| @@ -41,17 +42,17 @@ static av_cold int encode_init(AVCodecContext *avctx) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int encode_frame(AVCodecContext *avctx, unsigned char *buf, | |||||
| int buf_size, void *data) | |||||
| static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, | |||||
| const AVFrame *frame, int *got_packet) | |||||
| { | { | ||||
| 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; | |||||
| int x, y, z, length, tablesize; | |||||
| uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf, *buf; | |||||
| int x, y, z, length, tablesize, ret; | |||||
| unsigned int width, height, depth, dimension; | unsigned int width, height, depth, dimension; | ||||
| unsigned char *orig_buf = buf, *end_buf = buf + buf_size; | |||||
| unsigned char *end_buf; | |||||
| *p = *(AVFrame*)data; | |||||
| *p = *frame; | |||||
| p->pict_type = AV_PICTURE_TYPE_I; | p->pict_type = AV_PICTURE_TYPE_I; | ||||
| p->key_frame = 1; | p->key_frame = 1; | ||||
| @@ -76,12 +77,18 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, | |||||
| } | } | ||||
| tablesize = depth * height * 4; | tablesize = depth * height * 4; | ||||
| length = tablesize * 2 + SGI_HEADER_SIZE; | |||||
| if (buf_size < length) { | |||||
| av_log(avctx, AV_LOG_ERROR, "buf_size too small(need %d, got %d)\n", length, buf_size); | |||||
| return -1; | |||||
| length = SGI_HEADER_SIZE; | |||||
| if (avctx->coder_type == FF_CODER_TYPE_RAW) | |||||
| length += depth * height * width; | |||||
| else // assume ff_rl_encode() produces at most 2x size of input | |||||
| length += tablesize * 2 + depth * height * (2 * width + 1); | |||||
| if ((ret = ff_alloc_packet(pkt, length)) < 0) { | |||||
| av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", length); | |||||
| return ret; | |||||
| } | } | ||||
| buf = pkt->data; | |||||
| end_buf = pkt->data + pkt->size; | |||||
| /* Encode header. */ | /* Encode header. */ | ||||
| bytestream_put_be16(&buf, SGI_MAGIC); | bytestream_put_be16(&buf, SGI_MAGIC); | ||||
| @@ -124,7 +131,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, | |||||
| 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 - pkt->data); | |||||
| 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]; | ||||
| @@ -156,7 +163,11 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, | |||||
| } | } | ||||
| /* total length */ | /* total length */ | ||||
| return buf - orig_buf; | |||||
| pkt->size = buf - pkt->data; | |||||
| pkt->flags |= AV_PKT_FLAG_KEY; | |||||
| *got_packet = 1; | |||||
| return 0; | |||||
| } | } | ||||
| AVCodec ff_sgi_encoder = { | AVCodec ff_sgi_encoder = { | ||||
| @@ -165,7 +176,7 @@ AVCodec ff_sgi_encoder = { | |||||
| .id = CODEC_ID_SGI, | .id = CODEC_ID_SGI, | ||||
| .priv_data_size = sizeof(SgiContext), | .priv_data_size = sizeof(SgiContext), | ||||
| .init = encode_init, | .init = encode_init, | ||||
| .encode = encode_frame, | |||||
| .encode2 = encode_frame, | |||||
| .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"), | ||||
| }; | }; | ||||