| /* |
| * LCL (LossLess Codec Library) Codec |
| * Copyright (c) 2002-2004 Roberto Togni |
| * |
| * This file is part of FFmpeg. |
| * |
| * FFmpeg 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, |
| * 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 |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /** |
| * @file libavcodec/lclenc.c |
| * LCL (LossLess Codec Library) Video Codec |
| * Decoder for MSZH and ZLIB codecs |
| * Experimental encoder for ZLIB RGB24 |
| * |
| * Fourcc: MSZH, ZLIB |
| * |
| * Original Win32 dll: |
| * Ver2.23 By Kenji Oshima 2000.09.20 |
| * avimszh.dll, avizlib.dll |
| * |
| * A description of the decoding algorithm can be found here: |
| * http://www.pcisys.net/~melanson/codecs |
| * |
| * Supports: BGR24 (RGB 24bpp) |
| * |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include "avcodec.h" |
| #include "bitstream.h" |
| #include "lcl.h" |
| |
| #if CONFIG_ZLIB |
| #include <zlib.h> |
| #endif |
| |
| /* |
| * Decoder context |
| */ |
| typedef struct LclEncContext { |
| |
| AVCodecContext *avctx; |
| AVFrame pic; |
| PutBitContext pb; |
| |
| // Image type |
| int imgtype; |
| // Compression type |
| int compression; |
| // Flags |
| int flags; |
| // Decompressed data size |
| unsigned int decomp_size; |
| // Maximum compressed data size |
| unsigned int max_comp_size; |
| // Compression buffer |
| unsigned char* comp_buf; |
| #if CONFIG_ZLIB |
| z_stream zstream; |
| #endif |
| } LclEncContext; |
| |
| /* |
| * |
| * Encode a frame |
| * |
| */ |
| static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ |
| LclEncContext *c = avctx->priv_data; |
| AVFrame *pict = data; |
| AVFrame * const p = &c->pic; |
| int i; |
| int zret; // Zlib return code |
| |
| #if !CONFIG_ZLIB |
| av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled in.\n"); |
| return -1; |
| #else |
| |
| init_put_bits(&c->pb, buf, buf_size); |
| |
| *p = *pict; |
| p->pict_type= FF_I_TYPE; |
| p->key_frame= 1; |
| |
| if(avctx->pix_fmt != PIX_FMT_BGR24){ |
| av_log(avctx, AV_LOG_ERROR, "Format not supported!\n"); |
| return -1; |
| } |
| |
| zret = deflateReset(&(c->zstream)); |
| if (zret != Z_OK) { |
| av_log(avctx, AV_LOG_ERROR, "Deflate reset error: %d\n", zret); |
| return -1; |
| } |
| c->zstream.next_out = c->comp_buf; |
| c->zstream.avail_out = c->max_comp_size; |
| |
| for(i = avctx->height - 1; i >= 0; i--) { |
| c->zstream.next_in = p->data[0]+p->linesize[0]*i; |
| c->zstream.avail_in = avctx->width*3; |
| zret = deflate(&(c->zstream), Z_NO_FLUSH); |
| if (zret != Z_OK) { |
| av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); |
| return -1; |
| } |
| } |
| zret = deflate(&(c->zstream), Z_FINISH); |
| if (zret != Z_STREAM_END) { |
| av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); |
| return -1; |
| } |
| |
| for (i = 0; i < c->zstream.total_out; i++) |
| put_bits(&c->pb, 8, c->comp_buf[i]); |
| flush_put_bits(&c->pb); |
| |
| return c->zstream.total_out; |
| #endif |
| } |
| |
| /* |
| * |
| * Init lcl encoder |
| * |
| */ |
| static av_cold int encode_init(AVCodecContext *avctx) |
| { |
| LclEncContext *c = avctx->priv_data; |
| int zret; // Zlib return code |
| |
| #if !CONFIG_ZLIB |
| av_log(avctx, AV_LOG_ERROR, "Zlib support not compiled.\n"); |
| return 1; |
| #else |
| |
| c->avctx= avctx; |
| |
| assert(avctx->width && avctx->height); |
| |
| avctx->extradata= av_mallocz(8); |
| avctx->coded_frame= &c->pic; |
| |
| // Will be user settable someday |
| c->compression = 6; |
| c->flags = 0; |
| |
| switch(avctx->pix_fmt){ |
| case PIX_FMT_BGR24: |
| c->imgtype = IMGTYPE_RGB24; |
| c->decomp_size = avctx->width * avctx->height * 3; |
| avctx->bits_per_coded_sample= 24; |
| break; |
| default: |
| av_log(avctx, AV_LOG_ERROR, "Input pixel format %s not supported\n", avcodec_get_pix_fmt_name(avctx->pix_fmt)); |
| return -1; |
| } |
| |
| ((uint8_t*)avctx->extradata)[0]= 4; |
| ((uint8_t*)avctx->extradata)[1]= 0; |
| ((uint8_t*)avctx->extradata)[2]= 0; |
| ((uint8_t*)avctx->extradata)[3]= 0; |
| ((uint8_t*)avctx->extradata)[4]= c->imgtype; |
| ((uint8_t*)avctx->extradata)[5]= c->compression; |
| ((uint8_t*)avctx->extradata)[6]= c->flags; |
| ((uint8_t*)avctx->extradata)[7]= CODEC_ZLIB; |
| c->avctx->extradata_size= 8; |
| |
| c->zstream.zalloc = Z_NULL; |
| c->zstream.zfree = Z_NULL; |
| c->zstream.opaque = Z_NULL; |
| zret = deflateInit(&(c->zstream), c->compression); |
| if (zret != Z_OK) { |
| av_log(avctx, AV_LOG_ERROR, "Deflate init error: %d\n", zret); |
| return 1; |
| } |
| |
| /* Conservative upper bound taken from zlib v1.2.1 source */ |
| c->max_comp_size = c->decomp_size + ((c->decomp_size + 7) >> 3) + |
| ((c->decomp_size + 63) >> 6) + 11; |
| if ((c->comp_buf = av_malloc(c->max_comp_size)) == NULL) { |
| av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n"); |
| return 1; |
| } |
| |
| return 0; |
| #endif |
| } |
| |
| /* |
| * |
| * Uninit lcl encoder |
| * |
| */ |
| static av_cold int encode_end(AVCodecContext *avctx) |
| { |
| LclEncContext *c = avctx->priv_data; |
| |
| av_freep(&avctx->extradata); |
| av_freep(&c->comp_buf); |
| #if CONFIG_ZLIB |
| deflateEnd(&(c->zstream)); |
| #endif |
| |
| return 0; |
| } |
| |
| AVCodec zlib_encoder = { |
| "zlib", |
| CODEC_TYPE_VIDEO, |
| CODEC_ID_ZLIB, |
| sizeof(LclEncContext), |
| encode_init, |
| encode_frame, |
| encode_end, |
| .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), |
| }; |