Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavcodec
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 Libav.
6
*
7
* Libav 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
* Libav 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 Libav; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
38
#include <stdio.h>
39
#include <stdlib.h>
40
41
#include "
avcodec.h
"
42
#include "
msrledec.h
"
43
44
#include <zlib.h>
45
46
47
/*
48
* Decoder context
49
*/
50
typedef
struct
TsccContext
{
51
52
AVCodecContext
*
avctx
;
53
AVFrame
pic
;
54
55
// Bits per pixel
56
int
bpp
;
57
// Decompressed data size
58
unsigned
int
decomp_size
;
59
// Decompression buffer
60
unsigned
char
*
decomp_buf
;
61
GetByteContext
gb
;
62
int
height
;
63
z_stream
zstream
;
64
65
uint32_t
pal
[256];
66
}
CamtasiaContext
;
67
68
/*
69
*
70
* Decode a frame
71
*
72
*/
73
static
int
decode_frame
(
AVCodecContext
*avctx,
void
*
data
,
int
*data_size,
AVPacket
*avpkt)
74
{
75
const
uint8_t *buf = avpkt->
data
;
76
int
buf_size = avpkt->
size
;
77
CamtasiaContext
*
const
c = avctx->
priv_data
;
78
const
unsigned
char
*encoded = buf;
79
int
zret;
// Zlib return code
80
int
len
= buf_size;
81
82
if
(c->
pic
.
data
[0])
83
avctx->
release_buffer
(avctx, &c->
pic
);
84
85
c->
pic
.
reference
= 1;
86
c->
pic
.
buffer_hints
=
FF_BUFFER_HINTS_VALID
;
87
if
(avctx->
get_buffer
(avctx, &c->
pic
) < 0){
88
av_log
(avctx,
AV_LOG_ERROR
,
"get_buffer() failed\n"
);
89
return
-1;
90
}
91
92
zret = inflateReset(&c->
zstream
);
93
if
(zret != Z_OK) {
94
av_log
(avctx,
AV_LOG_ERROR
,
"Inflate reset error: %d\n"
, zret);
95
return
-1;
96
}
97
c->
zstream
.next_in = encoded;
98
c->
zstream
.avail_in =
len
;
99
c->
zstream
.next_out = c->
decomp_buf
;
100
c->
zstream
.avail_out = c->
decomp_size
;
101
zret = inflate(&c->
zstream
, Z_FINISH);
102
// Z_DATA_ERROR means empty picture
103
if
((zret != Z_OK) && (zret != Z_STREAM_END) && (zret != Z_DATA_ERROR)) {
104
av_log
(avctx,
AV_LOG_ERROR
,
"Inflate error: %d\n"
, zret);
105
return
-1;
106
}
107
108
109
if
(zret != Z_DATA_ERROR) {
110
bytestream2_init
(&c->
gb
, c->
decomp_buf
,
111
c->
decomp_size
- c->
zstream
.avail_out);
112
ff_msrle_decode
(avctx, (
AVPicture
*)&c->
pic
, c->
bpp
, &c->
gb
);
113
}
114
115
/* make the palette available on the way out */
116
if
(c->
avctx
->
pix_fmt
==
PIX_FMT_PAL8
) {
117
const
uint8_t *pal =
av_packet_get_side_data
(avpkt,
AV_PKT_DATA_PALETTE
,
NULL
);
118
119
if
(pal) {
120
c->
pic
.
palette_has_changed
= 1;
121
memcpy(c->
pal
, pal,
AVPALETTE_SIZE
);
122
}
123
memcpy(c->
pic
.
data
[1], c->
pal
,
AVPALETTE_SIZE
);
124
}
125
126
*data_size =
sizeof
(
AVFrame
);
127
*(
AVFrame
*)data = c->
pic
;
128
129
/* always report that the buffer was completely consumed */
130
return
buf_size;
131
}
132
133
134
135
/*
136
*
137
* Init tscc decoder
138
*
139
*/
140
static
av_cold
int
decode_init
(
AVCodecContext
*avctx)
141
{
142
CamtasiaContext
*
const
c = avctx->
priv_data
;
143
int
zret;
// Zlib return code
144
145
c->
avctx
= avctx;
146
147
c->
height
= avctx->
height
;
148
149
// Needed if zlib unused or init aborted before inflateInit
150
memset(&c->
zstream
, 0,
sizeof
(z_stream));
151
switch
(avctx->
bits_per_coded_sample
){
152
case
8: avctx->
pix_fmt
=
PIX_FMT_PAL8
;
break
;
153
case
16: avctx->
pix_fmt
=
PIX_FMT_RGB555
;
break
;
154
case
24:
155
avctx->
pix_fmt
=
PIX_FMT_BGR24
;
156
break
;
157
case
32: avctx->
pix_fmt
=
PIX_FMT_RGB32
;
break
;
158
default
:
av_log
(avctx,
AV_LOG_ERROR
,
"Camtasia error: unknown depth %i bpp\n"
, avctx->
bits_per_coded_sample
);
159
return
-1;
160
}
161
c->
bpp
= avctx->
bits_per_coded_sample
;
162
// buffer size for RLE 'best' case when 2-byte code precedes each pixel and there may be padding after it too
163
c->
decomp_size
= (((avctx->
width
* c->
bpp
+ 7) >> 3) + 3 * avctx->
width
+ 2) * avctx->
height
+ 2;
164
165
/* Allocate decompression buffer */
166
if (c->
decomp_size
) {
167
if
((c->
decomp_buf
=
av_malloc
(c->
decomp_size
)) ==
NULL
) {
168
av_log
(avctx,
AV_LOG_ERROR
,
"Can't allocate decompression buffer.\n"
);
169
return
1;
170
}
171
}
172
173
c->
zstream
.zalloc = Z_NULL;
174
c->
zstream
.zfree = Z_NULL;
175
c->
zstream
.opaque = Z_NULL;
176
zret = inflateInit(&c->
zstream
);
177
if
(zret != Z_OK) {
178
av_log
(avctx,
AV_LOG_ERROR
,
"Inflate init error: %d\n"
, zret);
179
return
1;
180
}
181
182
return
0;
183
}
184
185
186
187
/*
188
*
189
* Uninit tscc decoder
190
*
191
*/
192
static
av_cold
int
decode_end
(
AVCodecContext
*avctx)
193
{
194
CamtasiaContext
*
const
c = avctx->
priv_data
;
195
196
av_freep
(&c->
decomp_buf
);
197
198
if
(c->
pic
.
data
[0])
199
avctx->
release_buffer
(avctx, &c->
pic
);
200
inflateEnd(&c->
zstream
);
201
202
return
0;
203
}
204
205
AVCodec
ff_tscc_decoder
= {
206
.
name
=
"camtasia"
,
207
.type =
AVMEDIA_TYPE_VIDEO
,
208
.id =
CODEC_ID_TSCC
,
209
.priv_data_size =
sizeof
(
CamtasiaContext
),
210
.
init
=
decode_init
,
211
.
close
=
decode_end
,
212
.
decode
=
decode_frame
,
213
.capabilities =
CODEC_CAP_DR1
,
214
.long_name =
NULL_IF_CONFIG_SMALL
(
"TechSmith Screen Capture Codec"
),
215
};
216