1/* 2 * LCL (LossLess Codec Library) Codec 3 * Copyright (c) 2002-2004 Roberto Togni 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * LCL (LossLess Codec Library) Video Codec 25 * Decoder for MSZH and ZLIB codecs 26 * Experimental encoder for ZLIB RGB24 27 * 28 * Fourcc: MSZH, ZLIB 29 * 30 * Original Win32 dll: 31 * Ver2.23 By Kenji Oshima 2000.09.20 32 * avimszh.dll, avizlib.dll 33 * 34 * A description of the decoding algorithm can be found here: 35 * http://www.pcisys.net/~melanson/codecs 36 * 37 * Supports: BGR24 (RGB 24bpp) 38 * 39 */ 40 41#include <stdio.h> 42#include <stdlib.h> 43 44#include "libavutil/avassert.h" 45#include "avcodec.h" 46#include "internal.h" 47#include "lcl.h" 48#include "libavutil/internal.h" 49#include "libavutil/mem.h" 50 51#include <zlib.h> 52 53/* 54 * Decoder context 55 */ 56typedef struct LclEncContext { 57 58 AVCodecContext *avctx; 59 60 // Image type 61 int imgtype; 62 // Compression type 63 int compression; 64 // Flags 65 int flags; 66 z_stream zstream; 67} LclEncContext; 68 69/* 70 * 71 * Encode a frame 72 * 73 */ 74static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, 75 const AVFrame *p, int *got_packet) 76{ 77 LclEncContext *c = avctx->priv_data; 78 int i, ret; 79 int zret; // Zlib return code 80 int max_size = deflateBound(&c->zstream, avctx->width * avctx->height * 3); 81 82 if ((ret = ff_alloc_packet2(avctx, pkt, max_size)) < 0) 83 return ret; 84 85 if(avctx->pix_fmt != AV_PIX_FMT_BGR24){ 86 av_log(avctx, AV_LOG_ERROR, "Format not supported!\n"); 87 return -1; 88 } 89 90 zret = deflateReset(&c->zstream); 91 if (zret != Z_OK) { 92 av_log(avctx, AV_LOG_ERROR, "Deflate reset error: %d\n", zret); 93 return -1; 94 } 95 c->zstream.next_out = pkt->data; 96 c->zstream.avail_out = pkt->size; 97 98 for(i = avctx->height - 1; i >= 0; i--) { 99 c->zstream.next_in = p->data[0]+p->linesize[0]*i; 100 c->zstream.avail_in = avctx->width*3; 101 zret = deflate(&c->zstream, Z_NO_FLUSH); 102 if (zret != Z_OK) { 103 av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); 104 return -1; 105 } 106 } 107 zret = deflate(&c->zstream, Z_FINISH); 108 if (zret != Z_STREAM_END) { 109 av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); 110 return -1; 111 } 112 113 pkt->size = c->zstream.total_out; 114 pkt->flags |= AV_PKT_FLAG_KEY; 115 *got_packet = 1; 116 117 return 0; 118} 119 120/* 121 * 122 * Init lcl encoder 123 * 124 */ 125static av_cold int encode_init(AVCodecContext *avctx) 126{ 127 LclEncContext *c = avctx->priv_data; 128 int zret; // Zlib return code 129 130 c->avctx= avctx; 131 132 av_assert0(avctx->width && avctx->height); 133 134 avctx->extradata = av_mallocz(8 + FF_INPUT_BUFFER_PADDING_SIZE); 135 if (!avctx->extradata) 136 return AVERROR(ENOMEM); 137 138 avctx->coded_frame = av_frame_alloc(); 139 if (!avctx->coded_frame) 140 return AVERROR(ENOMEM); 141 142 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; 143 avctx->coded_frame->key_frame = 1; 144 145 c->compression = avctx->compression_level == FF_COMPRESSION_DEFAULT ? 146 COMP_ZLIB_NORMAL : 147 av_clip(avctx->compression_level, 0, 9); 148 c->flags = 0; 149 c->imgtype = IMGTYPE_RGB24; 150 avctx->bits_per_coded_sample= 24; 151 152 avctx->extradata[0]= 4; 153 avctx->extradata[1]= 0; 154 avctx->extradata[2]= 0; 155 avctx->extradata[3]= 0; 156 avctx->extradata[4]= c->imgtype; 157 avctx->extradata[5]= c->compression; 158 avctx->extradata[6]= c->flags; 159 avctx->extradata[7]= CODEC_ZLIB; 160 c->avctx->extradata_size= 8; 161 162 c->zstream.zalloc = Z_NULL; 163 c->zstream.zfree = Z_NULL; 164 c->zstream.opaque = Z_NULL; 165 zret = deflateInit(&c->zstream, c->compression); 166 if (zret != Z_OK) { 167 av_log(avctx, AV_LOG_ERROR, "Deflate init error: %d\n", zret); 168 return 1; 169 } 170 171 return 0; 172} 173 174/* 175 * 176 * Uninit lcl encoder 177 * 178 */ 179static av_cold int encode_end(AVCodecContext *avctx) 180{ 181 LclEncContext *c = avctx->priv_data; 182 183 av_freep(&avctx->extradata); 184 deflateEnd(&c->zstream); 185 186 av_frame_free(&avctx->coded_frame); 187 188 return 0; 189} 190 191AVCodec ff_zlib_encoder = { 192 .name = "zlib", 193 .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), 194 .type = AVMEDIA_TYPE_VIDEO, 195 .id = AV_CODEC_ID_ZLIB, 196 .priv_data_size = sizeof(LclEncContext), 197 .init = encode_init, 198 .encode2 = encode_frame, 199 .close = encode_end, 200 .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, 201 .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, 202}; 203