* TIFF image encoder
* Copyright (c) 2007 Bartlomiej Wolowiec
*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
*
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
+ * @file
* TIFF image encoder
- * @file libavcodec/tiffenc.c
* @author Bartlomiej Wolowiec
*/
+
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+
#include "avcodec.h"
#if CONFIG_ZLIB
#include <zlib.h>
};
typedef struct TiffEncoderContext {
+ AVClass *class; ///< for private options
AVCodecContext *avctx;
AVFrame picture;
* @param need Needed bytes
* @return 0 - ok, 1 - no free space
*/
-inline static int check_size(TiffEncoderContext * s, uint64_t need)
+static inline int check_size(TiffEncoderContext * s, uint64_t need)
{
if (s->buf_size < *s->buf - s->buf_start + need) {
*s->buf = s->buf_start + s->buf_size + 1;
}
}
-static int encode_frame(AVCodecContext * avctx, unsigned char *buf,
- int buf_size, void *data)
+static int encode_frame(AVCodecContext * avctx, AVPacket *pkt,
+ const AVFrame *pict, int *got_packet)
{
TiffEncoderContext *s = avctx->priv_data;
- AVFrame *pict = data;
- AVFrame *const p = (AVFrame *) & s->picture;
+ AVFrame *const p = &s->picture;
int i;
- int n;
- uint8_t *ptr = buf;
+ uint8_t *ptr;
uint8_t *offset;
uint32_t strips;
uint32_t *strip_sizes = NULL;
int bytes_per_row;
uint32_t res[2] = { 72, 1 }; // image resolution (72/1)
static const uint16_t bpp_tab[] = { 8, 8, 8, 8 };
- int ret = -1;
+ int ret;
int is_yuv = 0;
uint8_t *yuv_line = NULL;
int shift_h, shift_v;
- s->buf_start = buf;
- s->buf = &ptr;
- s->buf_size = buf_size;
+ s->avctx = avctx;
*p = *pict;
- p->pict_type = FF_I_TYPE;
+ p->pict_type = AV_PICTURE_TYPE_I;
p->key_frame = 1;
avctx->coded_frame= &s->picture;
- s->compr = TIFF_PACKBITS;
- if (avctx->compression_level == 0) {
- s->compr = TIFF_RAW;
- } else if(avctx->compression_level == 2) {
- s->compr = TIFF_LZW;
-#if CONFIG_ZLIB
- } else if ((avctx->compression_level >= 3)) {
- s->compr = TIFF_DEFLATE;
-#endif
- }
-
s->width = avctx->width;
s->height = avctx->height;
s->subsampling[0] = 1;
strips = (s->height - 1) / s->rps + 1;
+ if (!pkt->data &&
+ (ret = av_new_packet(pkt, avctx->width * avctx->height * s->bpp * 2 +
+ avctx->height * 4 + FF_MIN_BUFFER_SIZE)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
+ return ret;
+ }
+ ptr = pkt->data;
+ s->buf_start = pkt->data;
+ s->buf = &ptr;
+ s->buf_size = pkt->size;
+
if (check_size(s, 8))
goto fail;
zlen = bytes_per_row * s->rps;
zbuf = av_malloc(zlen);
- strip_offsets[0] = ptr - buf;
+ strip_offsets[0] = ptr - pkt->data;
zn = 0;
for (j = 0; j < s->rps; j++) {
if (is_yuv){
p->data[0] + j * p->linesize[0], bytes_per_row);
zn += bytes_per_row;
}
- n = encode_strip(s, zbuf, ptr, zn, s->compr);
+ ret = encode_strip(s, zbuf, ptr, zn, s->compr);
av_free(zbuf);
- if (n<0) {
+ if (ret < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n");
goto fail;
}
- ptr += n;
- strip_sizes[0] = ptr - buf - strip_offsets[0];
+ ptr += ret;
+ strip_sizes[0] = ptr - pkt->data - strip_offsets[0];
} else
#endif
{
ff_lzw_encode_init(s->lzws, ptr, s->buf_size - (*s->buf - s->buf_start),
12, FF_LZW_TIFF, put_bits);
}
- strip_offsets[i / s->rps] = ptr - buf;
+ strip_offsets[i / s->rps] = ptr - pkt->data;
}
if (is_yuv){
pack_yuv(s, yuv_line, i);
- n = encode_strip(s, yuv_line, ptr, bytes_per_row, s->compr);
+ ret = encode_strip(s, yuv_line, ptr, bytes_per_row, s->compr);
i += s->subsampling[1] - 1;
}
else
- n = encode_strip(s, p->data[0] + i * p->linesize[0],
+ ret = encode_strip(s, p->data[0] + i * p->linesize[0],
ptr, bytes_per_row, s->compr);
- if (n < 0) {
+ if (ret < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n");
goto fail;
}
- strip_sizes[i / s->rps] += n;
- ptr += n;
+ strip_sizes[i / s->rps] += ret;
+ ptr += ret;
if(s->compr == TIFF_LZW && (i==s->height-1 || i%s->rps == s->rps-1)){
- int ret;
ret = ff_lzw_encode_flush(s->lzws, flush_put_bits);
strip_sizes[(i / s->rps )] += ret ;
ptr += ret;
add_entry(s, TIFF_YCBCR_SUBSAMPLING, TIFF_SHORT, 2, s->subsampling);
add_entry(s, TIFF_REFERENCE_BW, TIFF_RATIONAL, 6, refbw);
}
- bytestream_put_le32(&offset, ptr - buf); // write offset to dir
+ bytestream_put_le32(&offset, ptr - pkt->data); // write offset to dir
- if (check_size(s, 6 + s->num_entries * 12))
+ if (check_size(s, 6 + s->num_entries * 12)) {
+ ret = AVERROR(EINVAL);
goto fail;
+ }
bytestream_put_le16(&ptr, s->num_entries); // write tag count
bytestream_put_buffer(&ptr, s->entries, s->num_entries * 12);
bytestream_put_le32(&ptr, 0);
- ret = ptr - buf;
+ pkt->size = ptr - pkt->data;
+ pkt->flags |= AV_PKT_FLAG_KEY;
+ *got_packet = 1;
fail:
av_free(strip_sizes);
return ret;
}
-AVCodec tiff_encoder = {
- "tiff",
- CODEC_TYPE_VIDEO,
- CODEC_ID_TIFF,
- sizeof(TiffEncoderContext),
- NULL,
- encode_frame,
- NULL,
- NULL,
- 0,
- NULL,
- .pix_fmts =
- (const enum PixelFormat[]) {PIX_FMT_RGB24, PIX_FMT_PAL8, PIX_FMT_GRAY8,
- PIX_FMT_MONOBLACK, PIX_FMT_MONOWHITE,
- PIX_FMT_YUV420P, PIX_FMT_YUV422P,
- PIX_FMT_YUV444P, PIX_FMT_YUV410P,
- PIX_FMT_YUV411P,
- PIX_FMT_NONE},
- .long_name = NULL_IF_CONFIG_SMALL("TIFF image"),
+#define OFFSET(x) offsetof(TiffEncoderContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+ { "compression_algo", NULL, OFFSET(compr), AV_OPT_TYPE_INT, {TIFF_PACKBITS}, TIFF_RAW, TIFF_DEFLATE, VE, "compression_algo" },
+ { "packbits", NULL, 0, AV_OPT_TYPE_CONST, {TIFF_PACKBITS}, 0, 0, VE, "compression_algo" },
+ { "raw", NULL, 0, AV_OPT_TYPE_CONST, {TIFF_RAW}, 0, 0, VE, "compression_algo" },
+ { "lzw", NULL, 0, AV_OPT_TYPE_CONST, {TIFF_LZW}, 0, 0, VE, "compression_algo" },
+#if CONFIG_ZLIB
+ { "deflate", NULL, 0, AV_OPT_TYPE_CONST, {TIFF_DEFLATE}, 0, 0, VE, "compression_algo" },
+#endif
+ { NULL },
+};
+
+static const AVClass tiffenc_class = {
+ .class_name = "TIFF encoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_tiff_encoder = {
+ .name = "tiff",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = CODEC_ID_TIFF,
+ .priv_data_size = sizeof(TiffEncoderContext),
+ .encode2 = encode_frame,
+ .pix_fmts = (const enum PixelFormat[]) {
+ PIX_FMT_RGB24, PIX_FMT_PAL8, PIX_FMT_GRAY8,
+ PIX_FMT_MONOBLACK, PIX_FMT_MONOWHITE,
+ PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P,
+ PIX_FMT_YUV410P, PIX_FMT_YUV411P,
+ PIX_FMT_NONE
+ },
+ .long_name = NULL_IF_CONFIG_SMALL("TIFF image"),
+ .priv_class = &tiffenc_class,
};