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