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