libavcodec/tscc.c

Go to the documentation of this file.
00001 /*
00002  * TechSmith Camtasia decoder
00003  * Copyright (c) 2004 Konstantin Shishkov
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 
00041 #include "avcodec.h"
00042 #include "msrledec.h"
00043 
00044 #include <zlib.h>
00045 
00046 
00047 /*
00048  * Decoder context
00049  */
00050 typedef struct TsccContext {
00051 
00052 AVCodecContext *avctx;
00053 AVFrame pic;
00054 
00055 // Bits per pixel
00056 int bpp;
00057 // Decompressed data size
00058 unsigned int decomp_size;
00059 // Decompression buffer
00060 unsigned char* decomp_buf;
00061 int height;
00062 z_stream zstream;
00063 
00064 uint32_t pal[256];
00065 } CamtasiaContext;
00066 
00067 /*
00068  *
00069  * Decode a frame
00070  *
00071  */
00072 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
00073 {
00074 const uint8_t *buf = avpkt->data;
00075 int buf_size = avpkt->size;
00076 CamtasiaContext * const c = avctx->priv_data;
00077 const unsigned char *encoded = buf;
00078 int zret; // Zlib return code
00079 int len = buf_size;
00080 
00081 if(c->pic.data[0])
00082 avctx->release_buffer(avctx, &c->pic);
00083 
00084 c->pic.reference = 1;
00085 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
00086 if(avctx->get_buffer(avctx, &c->pic) < 0){
00087 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00088 return -1;
00089 }
00090 
00091 zret = inflateReset(&(c->zstream));
00092 if (zret != Z_OK) {
00093 av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
00094 return -1;
00095 }
00096 c->zstream.next_in = encoded;
00097 c->zstream.avail_in = len;
00098 c->zstream.next_out = c->decomp_buf;
00099 c->zstream.avail_out = c->decomp_size;
00100 zret = inflate(&(c->zstream), Z_FINISH);
00101 // Z_DATA_ERROR means empty picture
00102 if ((zret != Z_OK) && (zret != Z_STREAM_END) && (zret != Z_DATA_ERROR)) {
00103 av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", zret);
00104 return -1;
00105 }
00106 
00107 
00108 if(zret != Z_DATA_ERROR)
00109 ff_msrle_decode(avctx, (AVPicture*)&c->pic, c->bpp, c->decomp_buf, c->decomp_size - c->zstream.avail_out);
00110 
00111 /* make the palette available on the way out */
00112 if (c->avctx->pix_fmt == PIX_FMT_PAL8) {
00113 const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
00114 
00115 if (pal) {
00116 c->pic.palette_has_changed = 1;
00117 memcpy(c->pal, pal, AVPALETTE_SIZE);
00118 }
00119 memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE);
00120 }
00121 
00122 *data_size = sizeof(AVFrame);
00123 *(AVFrame*)data = c->pic;
00124 
00125 /* always report that the buffer was completely consumed */
00126 return buf_size;
00127 }
00128 
00129 
00130 
00131 /*
00132  *
00133  * Init tscc decoder
00134  *
00135  */
00136 static av_cold int decode_init(AVCodecContext *avctx)
00137 {
00138 CamtasiaContext * const c = avctx->priv_data;
00139 int zret; // Zlib return code
00140 
00141 c->avctx = avctx;
00142 
00143 c->height = avctx->height;
00144 
00145 avcodec_get_frame_defaults(&c->pic);
00146 // Needed if zlib unused or init aborted before inflateInit
00147 memset(&(c->zstream), 0, sizeof(z_stream));
00148 switch(avctx->bits_per_coded_sample){
00149 case 8: avctx->pix_fmt = PIX_FMT_PAL8; break;
00150 case 16: avctx->pix_fmt = PIX_FMT_RGB555; break;
00151 case 24:
00152 avctx->pix_fmt = PIX_FMT_BGR24;
00153 break;
00154 case 32: avctx->pix_fmt = PIX_FMT_RGB32; break;
00155 default: av_log(avctx, AV_LOG_ERROR, "Camtasia error: unknown depth %i bpp\n", avctx->bits_per_coded_sample);
00156 return -1;
00157 }
00158 c->bpp = avctx->bits_per_coded_sample;
00159 // buffer size for RLE 'best' case when 2-byte code preceeds each pixel and there may be padding after it too
00160 c->decomp_size = (((avctx->width * c->bpp + 7) >> 3) + 3 * avctx->width + 2) * avctx->height + 2;
00161 
00162 /* Allocate decompression buffer */
00163 if (c->decomp_size) {
00164 if ((c->decomp_buf = av_malloc(c->decomp_size)) == NULL) {
00165 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
00166 return 1;
00167 }
00168 }
00169 
00170 c->zstream.zalloc = Z_NULL;
00171 c->zstream.zfree = Z_NULL;
00172 c->zstream.opaque = Z_NULL;
00173 zret = inflateInit(&(c->zstream));
00174 if (zret != Z_OK) {
00175 av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
00176 return 1;
00177 }
00178 
00179 return 0;
00180 }
00181 
00182 
00183 
00184 /*
00185  *
00186  * Uninit tscc decoder
00187  *
00188  */
00189 static av_cold int decode_end(AVCodecContext *avctx)
00190 {
00191 CamtasiaContext * const c = avctx->priv_data;
00192 
00193 av_freep(&c->decomp_buf);
00194 
00195 if (c->pic.data[0])
00196 avctx->release_buffer(avctx, &c->pic);
00197 inflateEnd(&(c->zstream));
00198 
00199 return 0;
00200 }
00201 
00202 AVCodec ff_tscc_decoder = {
00203 "camtasia",
00204 AVMEDIA_TYPE_VIDEO,
00205 CODEC_ID_TSCC,
00206 sizeof(CamtasiaContext),
00207 decode_init,
00208 NULL,
00209 decode_end,
00210 decode_frame,
00211 CODEC_CAP_DR1,
00212 .long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Capture Codec"),
00213 };
00214 

Generated on Fri Oct 26 02:39:37 2012 for FFmpeg by doxygen 1.5.8

AltStyle によって変換されたページ (->オリジナル) /