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