FFmpeg
Loading...
Searching...
No Matches
tscc.c
Go to the documentation of this file.
1/*
2 * TechSmith Camtasia decoder
3 * Copyright (c) 2004 Konstantin Shishkov
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 * TechSmith Camtasia decoder
25 *
26 * Fourcc: TSCC
27 *
28 * Codec is very simple:
29 * it codes picture (picture difference, really)
30 * with algorithm almost identical to Windows RLE8,
31 * only without padding and with greater pixel sizes,
32 * then this coded picture is packed with ZLib
33 *
34 * Supports: BGR8,BGR555,BGR24 - only BGR8 and BGR555 tested
35 */
36
37#include "libavutil/mem.h"
38#include "avcodec.h"
39#include "codec_internal.h"
40#include "decode.h"
41#include "msrledec.h"
42#include "zlib_wrapper.h"
43
44#include <zlib.h>
45
46typedef struct TsccContext {
47
50
51 // Bits per pixel
52 int bpp;
53 // Decompressed data size
54 unsigned int decomp_size;
55 // Decompression buffer
56 unsigned char* decomp_buf;
58 int height;
60
61 uint32_t pal[256];
63
64static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
65 int *got_frame, AVPacket *avpkt)
66{
67 const uint8_t *buf = avpkt->data;
68 int buf_size = avpkt->size;
69 CamtasiaContext * const c = avctx->priv_data;
70 z_stream *const zstream = &c->zstream.zstream;
71 AVFrame *frame = c->frame;
72 int ret;
73 int palette_has_changed = 0;
74
75 if (c->avctx->pix_fmt == AV_PIX_FMT_PAL8) {
76 palette_has_changed = ff_copy_palette(c->pal, avpkt, avctx);
77 }
78
79 ret = inflateReset(zstream);
80 if (ret != Z_OK) {
81 av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
82 return AVERROR_UNKNOWN;
83 }
84 zstream->next_in = buf;
85 zstream->avail_in = buf_size;
86 zstream->next_out = c->decomp_buf;
87 zstream->avail_out = c->decomp_size;
88 ret = inflate(zstream, Z_FINISH);
89 // Z_DATA_ERROR means empty picture
90 if (ret == Z_DATA_ERROR && !palette_has_changed) {
91 return buf_size;
92 }
93
94 if ((ret != Z_OK) && (ret != Z_STREAM_END) && (ret != Z_DATA_ERROR)) {
95 av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret);
96 return AVERROR_UNKNOWN;
97 }
98
99 if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
100 return ret;
101
102 if (ret != Z_DATA_ERROR) {
103 bytestream2_init(&c->gb, c->decomp_buf,
104 c->decomp_size - zstream->avail_out);
105 ff_msrle_decode(avctx, frame, c->bpp, &c->gb);
106 }
107
108 /* make the palette available on the way out */
109 if (c->avctx->pix_fmt == AV_PIX_FMT_PAL8) {
110 memcpy(frame->data[1], c->pal, AVPALETTE_SIZE);
111 }
112
113 if ((ret = av_frame_ref(rframe, frame)) < 0)
114 return ret;
115 *got_frame = 1;
116
117 /* always report that the buffer was completely consumed */
118 return buf_size;
119}
120
122{
123 CamtasiaContext * const c = avctx->priv_data;
124
125 c->avctx = avctx;
126
127 c->height = avctx->height;
128
129 switch(avctx->bits_per_coded_sample){
130 case 8: avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
131 case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
132 case 24:
133 avctx->pix_fmt = AV_PIX_FMT_BGR24;
134 break;
135 case 32: avctx->pix_fmt = AV_PIX_FMT_0RGB32; break;
136 default: av_log(avctx, AV_LOG_ERROR, "Camtasia error: unknown depth %i bpp\n", avctx->bits_per_coded_sample);
138 }
139 c->bpp = avctx->bits_per_coded_sample;
140 // buffer size for RLE 'best' case when 2-byte code precedes each pixel and there may be padding after it too
141 c->decomp_size = (((avctx->width * c->bpp + 7) >> 3) + 3 * avctx->width + 2) * avctx->height + 2;
142
143 /* Allocate decompression buffer */
144 if (c->decomp_size) {
145 if (!(c->decomp_buf = av_malloc(c->decomp_size))) {
146 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
147 return AVERROR(ENOMEM);
148 }
149 }
150
151 c->frame = av_frame_alloc();
152 if (!c->frame)
153 return AVERROR(ENOMEM);
154
155 return ff_inflate_init(&c->zstream, avctx);
156}
157
159{
160 CamtasiaContext * const c = avctx->priv_data;
161
162 av_freep(&c->decomp_buf);
163 av_frame_free(&c->frame);
164 ff_inflate_end(&c->zstream);
165
166 return 0;
167}
168
170 .p.name = "camtasia",
171 CODEC_LONG_NAME("TechSmith Screen Capture Codec"),
172 .p.type = AVMEDIA_TYPE_VIDEO,
173 .p.id = AV_CODEC_ID_TSCC,
174 .priv_data_size = sizeof(CamtasiaContext),
175 .init = decode_init,
176 .close = decode_end,
178 .p.capabilities = AV_CODEC_CAP_DR1,
179 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
180};
const FFCodec ff_tscc_decoder
Definition tscc.c:169
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
Libavcodec external API header.
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition bytestream.h:137
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Identical in function to ff_get_buffer(), except it reuses the existing buffer if available.
Definition decode.c:1906
int ff_copy_palette(void *dst, const AVPacket *src, void *logctx)
Check whether the side-data of src contains a palette of size AVPALETTE_SIZE; if so,...
Definition decode.c:2321
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_TSCC
Definition codec_id.h:106
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR(e)
Definition error.h:45
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition frame.c:278
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
static av_cold int decode_init(AVCodecContext *avctx)
Definition 4xm.c:998
static av_cold int decode_end(AVCodecContext *avctx)
Definition 4xm.c:980
static int decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt)
Definition 4xm.c:837
#define av_cold
Definition attributes.h:117
Memory handling functions.
int ff_msrle_decode(AVCodecContext *avctx, AVFrame *pic, int depth, GetByteContext *gb)
Decode stream in MS RLE format into frame.
Definition msrledec.c:249
#define av_malloc(s)
Definition ops_static.c:52
#define AV_PIX_FMT_0RGB32
Definition pixfmt.h:521
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition pixfmt.h:84
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
#define AVPALETTE_SIZE
Definition pixfmt.h:32
#define AV_PIX_FMT_RGB555
Definition pixfmt.h:533
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
Definition avcodec.h:1564
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
AVFrame * frame
Definition tscc.c:49
FFZStream zstream
Definition tscc.c:59
unsigned char * decomp_buf
Definition tscc.c:56
uint32_t pal[256]
Definition tscc.c:61
GetByteContext gb
Definition tscc.c:57
AVCodecContext * avctx
Definition tscc.c:48
unsigned int decomp_size
Definition tscc.c:54
#define av_freep(p)
#define av_log(a,...)
static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt)
Definition tscc.c:64
static av_cold int decode_init(AVCodecContext *avctx)
Definition tscc.c:121
static av_cold int decode_end(AVCodecContext *avctx)
Definition tscc.c:158
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
static double c[64]
void ff_inflate_end(FFZStream *zstream)
Wrapper around inflateEnd().
int ff_inflate_init(FFZStream *zstream, void *logctx)
Wrapper around inflateInit().