FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
anm.c
Go to the documentation of this file.
1
/*
2
* Deluxe Paint Animation demuxer
3
* Copyright (c) 2009 Peter Ross
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
* Deluxe Paint Animation demuxer
25
*/
26
27
#include "
libavutil/intreadwrite.h
"
28
#include "
avformat.h
"
29
#include "
internal.h
"
30
31
typedef
struct
{
32
int
base_record
;
33
unsigned
int
nb_records
;
34
int
size
;
35
}
Page
;
36
37
typedef
struct
{
38
unsigned
int
nb_pages
;
/**< total pages in file */
39
unsigned
int
nb_records
;
/**< total records in file */
40
int
page_table_offset
;
41
#define MAX_PAGES 256
/**< Deluxe Paint hardcoded value */
42
Page
pt
[
MAX_PAGES
];
/**< page table */
43
int
page
;
/**< current page (or AVERROR_xxx code) */
44
int
record
;
/**< current record (with in page) */
45
}
AnmDemuxContext
;
46
47
#define LPF_TAG MKTAG('L','P','F',' ')
48
#define ANIM_TAG MKTAG('A','N','I','M')
49
50
static
int
probe
(
AVProbeData
*p)
51
{
52
/* verify tags and video dimensions */
53
if
(
AV_RL32
(&p->
buf
[0]) ==
LPF_TAG
&&
54
AV_RL32
(&p->
buf
[16]) ==
ANIM_TAG
&&
55
AV_RL16
(&p->
buf
[20]) &&
AV_RL16
(&p->
buf
[22]))
56
return
AVPROBE_SCORE_MAX
;
57
return
0;
58
}
59
60
/**
61
* @return page containing the requested record or AVERROR_XXX
62
*/
63
static
int
find_record
(
const
AnmDemuxContext
*anm,
int
record)
64
{
65
int
i;
66
67
if
(record >= anm->
nb_records
)
68
return
AVERROR_EOF
;
69
70
for
(i = 0; i <
MAX_PAGES
; i++) {
71
const
Page
*p = &anm->
pt
[i];
72
if
(p->
nb_records
> 0 && record >= p->
base_record
&& record < p->base_record + p->
nb_records
)
73
return
i;
74
}
75
76
return
AVERROR_INVALIDDATA
;
77
}
78
79
static
int
read_header
(
AVFormatContext
*
s
)
80
{
81
AnmDemuxContext
*anm = s->
priv_data
;
82
AVIOContext
*pb = s->
pb
;
83
AVStream
*st;
84
int
i,
ret
;
85
86
avio_skip
(pb, 4);
/* magic number */
87
if
(
avio_rl16
(pb) !=
MAX_PAGES
) {
88
avpriv_request_sample
(s,
"max_pages != "
AV_STRINGIFY
(
MAX_PAGES
));
89
return
AVERROR_PATCHWELCOME
;
90
}
91
92
anm->
nb_pages
=
avio_rl16
(pb);
93
anm->
nb_records
=
avio_rl32
(pb);
94
avio_skip
(pb, 2);
/* max records per page */
95
anm->
page_table_offset
=
avio_rl16
(pb);
96
if
(
avio_rl32
(pb) !=
ANIM_TAG
)
97
return
AVERROR_INVALIDDATA
;
98
99
/* video stream */
100
st =
avformat_new_stream
(s, NULL);
101
if
(!st)
102
return
AVERROR
(ENOMEM);
103
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
104
st->
codec
->
codec_id
=
AV_CODEC_ID_ANM
;
105
st->
codec
->
codec_tag
= 0;
/* no fourcc */
106
st->
codec
->
width
=
avio_rl16
(pb);
107
st->
codec
->
height
=
avio_rl16
(pb);
108
if
(
avio_r8
(pb) != 0)
109
goto
invalid;
110
avio_skip
(pb, 1);
/* frame rate multiplier info */
111
112
/* ignore last delta record (used for looping) */
113
if
(
avio_r8
(pb))
/* has_last_delta */
114
anm->
nb_records
=
FFMAX
(anm->
nb_records
- 1, 0);
115
116
avio_skip
(pb, 1);
/* last_delta_valid */
117
118
if
(
avio_r8
(pb) != 0)
119
goto
invalid;
120
121
if
(
avio_r8
(pb) != 1)
122
goto
invalid;
123
124
avio_skip
(pb, 1);
/* other recs per frame */
125
126
if
(
avio_r8
(pb) != 1)
127
goto
invalid;
128
129
avio_skip
(pb, 32);
/* record_types */
130
st->
nb_frames
=
avio_rl32
(pb);
131
avpriv_set_pts_info
(st, 64, 1,
avio_rl16
(pb));
132
avio_skip
(pb, 58);
133
134
/* color cycling and palette data */
135
st->
codec
->
extradata_size
= 16*8 + 4*256;
136
st->
codec
->
extradata
=
av_mallocz
(st->
codec
->
extradata_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
137
if
(!st->
codec
->
extradata
) {
138
return
AVERROR
(ENOMEM);
139
}
140
ret =
avio_read
(pb, st->
codec
->
extradata
, st->
codec
->
extradata_size
);
141
if
(ret < 0)
142
return
ret
;
143
144
/* read page table */
145
ret =
avio_seek
(pb, anm->
page_table_offset
, SEEK_SET);
146
if
(ret < 0)
147
return
ret
;
148
149
for
(i = 0; i <
MAX_PAGES
; i++) {
150
Page
*p = &anm->
pt
[i];
151
p->
base_record
=
avio_rl16
(pb);
152
p->
nb_records
=
avio_rl16
(pb);
153
p->
size
=
avio_rl16
(pb);
154
}
155
156
/* find page of first frame */
157
anm->
page
=
find_record
(anm, 0);
158
if
(anm->
page
< 0) {
159
return
anm->
page
;
160
}
161
162
anm->
record
= -1;
163
return
0;
164
165
invalid:
166
avpriv_request_sample
(s,
"Invalid header element"
);
167
return
AVERROR_PATCHWELCOME
;
168
}
169
170
static
int
read_packet
(
AVFormatContext
*
s
,
171
AVPacket
*
pkt
)
172
{
173
AnmDemuxContext
*anm = s->
priv_data
;
174
AVIOContext
*pb = s->
pb
;
175
Page
*p;
176
int
tmp, record_size;
177
178
if
(
url_feof
(s->
pb
))
179
return
AVERROR
(EIO);
180
181
if
(anm->
page
< 0)
182
return
anm->
page
;
183
184
repeat:
185
p = &anm->
pt
[anm->
page
];
186
187
/* parse page header */
188
if
(anm->
record
< 0) {
189
avio_seek
(pb, anm->
page_table_offset
+
MAX_PAGES
*6 + (anm->
page
<<16), SEEK_SET);
190
avio_skip
(pb, 8 + 2*p->
nb_records
);
191
anm->
record
= 0;
192
}
193
194
/* if we have fetched all records in this page, then find the
195
next page and repeat */
196
if
(anm->
record
>= p->
nb_records
) {
197
anm->
page
=
find_record
(anm, p->
base_record
+ p->
nb_records
);
198
if
(anm->
page
< 0)
199
return
anm->
page
;
200
anm->
record
= -1;
201
goto
repeat;
202
}
203
204
/* fetch record size */
205
tmp =
avio_tell
(pb);
206
avio_seek
(pb, anm->
page_table_offset
+
MAX_PAGES
*6 + (anm->
page
<<16) +
207
8 + anm->
record
* 2, SEEK_SET);
208
record_size =
avio_rl16
(pb);
209
avio_seek
(pb, tmp, SEEK_SET);
210
211
/* fetch record */
212
pkt->
size
=
av_get_packet
(s->
pb
, pkt, record_size);
213
if
(pkt->
size
< 0)
214
return
pkt->
size
;
215
if
(p->
base_record
+ anm->
record
== 0)
216
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
217
218
anm->
record
++;
219
return
0;
220
}
221
222
AVInputFormat
ff_anm_demuxer
= {
223
.
name
=
"anm"
,
224
.long_name =
NULL_IF_CONFIG_SMALL
(
"Deluxe Paint Animation"
),
225
.priv_data_size =
sizeof
(
AnmDemuxContext
),
226
.
read_probe
=
probe
,
227
.
read_header
=
read_header
,
228
.
read_packet
=
read_packet
,
229
};
Generated on Sun Mar 23 2014 23:49:51 for FFmpeg by
1.8.2